天天看點

[Effective JavaScript 筆記]第44條:使用null原型以防止原型污染

[Effective JavaScript 筆記]第44條:使用null原型以防止原型污染

ES5提供了标準方法來建立一個沒有原型的對象。Object.create函數能夠使用一個使用者指定的原型鍊和一個屬性描述符動态地構造對象。屬性描述符描述了新對象屬性的值及特性。通過簡單傳遞一個null原型參數和一個空的描述符,就可以建立一個真正的空對象。

第43條中講到的就算是用了Object的直接執行個體,也無法完全避免,Object.prototype對象修改,造成的原型污染。防止原型污染最簡單的方式之一就是不使用原型。在ES5之前,并沒有标準的方式建立一個空原型的新對象。

嘗試

設定構造函數的原型屬性為null或undefined

function C(){}
C.prototype=null;
           

結果

執行個體化該構造函數仍然得到是Object的執行個體。

var c=new C();
Object.getPrototypeOf(c) === null;//false
Object.getPrototypeOf(c) === Object.prototype;//true           

ES5标準方法

var x=Object.create(null);
Object.getPrototypeOf(x)==null;//true           

原型污染無法影響這樣的對象。

相容版本

一些不支援Object.create函數的舊的js環境可能支援__proto__屬性,對象字面量也支援初始化一個原型鍊為null的新對象。

var x={__proto__:null};
x instanceof Object;//false           

上面的方法也很有效,但在有标準方法後,标準方法是更好的選擇。

注意

__proto__屬性是非标準的并且并不是所有環境都可以移植的。js的實作者們并不能保證以後仍然支援它,是以有标準方法,盡量先考慮标準方法。

可以看出,雖然__proto__可以解決問題,但也引入它自身平台不相容的問題,阻止自由原型對象作為真正健壯的字典實作。更健壯的方法,在下一條中會提到。

提示

  • 在ES5環境中,使用Object.create(null)建立的自由原型的空對象是不太容易被污染的
  • 在一些較老的環境中,考慮使用{__proto__:null}
  • 但要注意__proto__既不标準,也不是完全可移植的,并且可能會在未來的js環境中去除
  • 絕不要使用"__proto__"名作為字典的key,因為一些環境将其作為特殊的屬性對待。

版權聲明

翻譯的文章,版權歸原作者所有,隻用于交流與學習的目的。

原創文章,版權歸作者所有,非商業轉載請注明出處,并保留原文的完整連結。

繼續閱讀