1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        如何禁止JavaScript對象重寫?

        共 3666字,需瀏覽 8分鐘

         ·

        2021-02-19 13:29

        來源 |?http://piotrwalat.net/

        翻譯 |?Fundebug


        由于JavaScript的靈活性,我們可以輕易地重寫(override)一些于其他人定義的對象(object)。
        換句話說,任何人都可以重寫我們所定義的對象。
        這是一個非常強大的特性,許多開發(fā)者都有興趣試試,來拓展或者修改某些對象的行為。
        例如,DOM方法document.getElementById()都可以被重寫。
        一般來講,我們應該避免這樣做,因為這會導致代碼很難維護,并且會留下一些難于發(fā)現(xiàn)的BUG。
        ECMAScript 5引入了一些方法,允許開發(fā)者限制對象重寫。
        如果你在開發(fā)一些工具庫比如jQuery,?fundebug等, 或者你的開發(fā)團隊非常大,本文介紹的這些方法將非常有用。

        不要重寫他人的對象

        不要重寫他人的對象,這是JavaScript的黃金法則。比如,當你重寫了一個方法,則很可能這會影響依賴于該方法的庫,這會讓其他開發(fā)者非常困惑。
        // 示例代碼1window.originalAlert = window.alert;  window.alert = function(msg) {      if (typeof msg === "string") {        return console.log(msg);    }    return window.originalAlert(msg);};
        alert('ooh so awesome'); // 參數(shù)為字符串時,打印到控制臺 alert(3.14); // 參數(shù)為其他類型時,彈出對話框

        在示例代碼1中,我修改了windows.alert:參數(shù)為字符串時,打印到控制臺;參數(shù)為其他類型時,彈出對話框。這樣的修改顯然會影響其他使用alert方法的開發(fā)者。

        如果你修改的是DOM對象比如getElementById(),這會導致非常嚴重的后果。

        如果你只是為對象添加新的方法,這也會導致問題。

        // 示例代碼2Math.cube = function(n) {      return Math.pow(n, 3);};console.log(Math.cube(2)); // 8

        這樣做最大的問題是有可能在未來導致命名沖突。盡管Math對象目前并沒有cube方法,下一個版本的JavaScript標準也許會增加cube方法(當然可能性不大),這就意味著我們會把原生cube方法給替代了。

        有一個真實的案例,Prototype庫定義了document.getElementsByClassName()方法,而這個方法后來被加入了JavaScript標準。

        不幸的是,我們無法阻止其他開發(fā)者重寫我們定義的對象,這時我們就需要本文介紹的這些方法了:

        首先,我們不妨通過一個表格對比一下Object.preventExtensions()、Object.seal()和Object.freeze():

        方法禁止增加屬性禁止刪除屬性禁止修改屬性
        Object.preventExtensions()
        Object.seal()
        Object.freeze()

        Object.preventExtensions()

        使用Object.preventExtensions(),可以禁止給對象添加新的方法或者屬性。注意,修改或者刪除對象已經(jīng)存在的方法或者屬性是沒有問題的。使用Object.isExtensible()可以查看某個對象是否可以增加方法或者屬性。

        // 示例代碼3var song = {      title: 'Hope Leaves',    artist: 'Opeth'};

        console.log(Object.isExtensible(song)); //true Object.preventExtensions(song); console.log(Object.isExtensible(song)); //false

        song.album = 'Damnation';console.log(song.album); // undefined

        song.play = function() { console.log('ahh soo awesome');};song.play(); // TypeError: song.play is not a function

        由示例代碼3可知,執(zhí)行Object.preventExtensions()之后,為song對象新增album以及play方法都失敗了!

        但是,當我們?yōu)閟ong新增屬性或者方法時,并沒有報錯。當我們使用了”use strict”采用嚴格模式時,情況就不一樣了:

        // 示例代碼4"use strict";
        var song = { title: 'Hope Leaves', artist: 'Opeth'};
        Object.preventExtensions(song);
        song.album = 'Damnation'; // Uncaught TypeError: Cannot add property album, object is not extensible

        在嚴格模式下,給已經(jīng)Object.preventExtensions的對象新增屬性時,會立即報錯。

        Object.seal()

        使用Object.seal(),可以禁止給對象添加屬性或者方法(這一點與Object.preventExtension()的作用一致),同時禁止刪除對象已經(jīng)存在的屬性或者方法。

        // 示例代碼5"use strict"var song = {    title: 'Hope Leaves',    artist: 'Opeth'};
        Object.seal(song);console.log(Object.isExtensible(song)); //false console.log(Object.isSealed(song)); //true
        song.album = 'Damnation'; // Uncaught TypeError: Cannot add property album, object is not extensibledelete song.artist; // Uncaught TypeError: Cannot delete property 'artist' of #

        Object.freeze()

        使用Object.freeze(),可以禁止為對象增加屬性或者方法(這一點與Object.preventExtension()的作用一致),同時禁止刪除對象已經(jīng)存在的屬性或者方法(這一點與Object.seal()的作用一致),另外還禁止修改已經(jīng)存在的屬性或者方法。

        // 示例代碼6"use strict"var song = {    title: 'Hope Leaves',    artist: 'Opeth',    getLongTitle: function(){        return this.artist + " - " + this.title;    }};
        Object.freeze(song);
        console.log(Object.isExtensible(song)); // false console.log(Object.isSealed(song)); // true console.log(Object.isFrozen(song)); // true
        song.album = 'Damnation'; // Uncaught TypeError: Cannot add property album, object is not extensible delete song.artist; // Uncaught TypeError: Cannot delete property 'artist' of # song.getLongTitle = function() // Uncaught TypeError: Cannot assign to read only property 'getLongTitle' of object '#'{ return "foobar";};

        主流瀏覽器的最新版本都支持這些方法:

        • IE 9+

        • Firefox 4+

        • Safari 5.1+

        • Chrome 7+

        • Opera 12+



        本文完?

        瀏覽 43
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

          <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            91国产丝袜在线播放 | A片在线观看网址 | 亚洲最新无码视频 | 天天操天天射天天插 | 视频一区二区三区四区五区六区 | 成人做爰高潮片免费视频QQ群 | 欧美一区二区性爱视频 | 精品无码一区二区三区四区 | 操逼极品 | 一级毛片无码 |