var book = { _year: 2004, edition: 1 }; Object.defineProperty(book, "year", { get: function(){ return 2018; }, set: function(newValue){ if (newValue > 2004) { this._year = newValue; this.edition += newValue - 2004; } } }); console.log(book.year);//2018 book.year = 2005; console.log(book.year);//2018
爲何下面第一種方式會報錯而第二種不會?javascript
//構造函數建立 var object=new Object(); object.x=1; object.2=1; //Unexpected number //字面量建立 var object = { x: 1, 2: 2 };//不報錯
分析以下:html
window.2=2; //假設不會出錯 2==2;//這個地方應該怎麼處理?--無法處理
那麼字面量爲何不會出錯?往下看
當啓用慢模式時以Hash做爲底層存儲結構,key爲字符串,字面量方式會存在類型轉換。java
對象大多數時候表現爲Dictionary:以字符串爲key,任意object爲值。可是...往下看chrome
命名屬性:
如:{a:'foo',b:'bar'}數組
數組索引屬性(元素):
如:數組['foo','bar']有兩個數組索引屬性:0,值爲'foo'; 1,值爲'bar'。緩存
數組索引屬性和命名屬性存儲在兩個單獨的數據結構中:
數據結構
每一個JS對象都有一個隱藏類與之關聯。
隱藏類存儲有對象結構信息(屬性數和對對象原型的引用),以及從屬性名稱到屬性的索引映射。
隱藏類是動態建立的,並隨着對象的變化而動態更新。ide
在V8中,位於堆內存並由GC管理的全部JS對象的第一個字段都指向隱藏類。
隱藏類存儲中包含屬性的數量,和一個指向描述符數組的指針。
在這個描述符數組中包含有命名屬性的信息,例如命名屬性的名稱和存儲屬性值的位置。函數
注意:具備相同結構的JS對象(相同順序和相同命名的屬性),他們的隱藏類會指向同一個,以此達到複用的目的。對於不一樣結構的JS對象將使用不一樣的HiddenClass。this
每次添加新屬性時,都會更改對象的HiddenClass。V8維護了一個把HiddenClasses連接在一塊兒的轉換樹。按相同屬性添加順序將獲得同樣的隱藏類。
若是咱們建立一個添加了不一樣屬性的新對象('d'),則會建立一個單獨的隱藏類分支。
結論:
具備相同結構的對象(相同屬性的相同順序)具備相同的HiddenClass
默認狀況下,每一個添加的新命名屬性都會致使建立一個新的HiddenClass。
添加數組索引屬性不會建立新的HiddenClasses。
注意:過多的添加或刪除屬性,會從快屬性模式切換爲慢屬性模式。
結論:
三種不一樣的命名屬性類型:in-object,fast和slow(dictionary)。
內嵌屬性直接存儲在對象自己上,並提供最快的訪問。
快速屬性存在於屬性存儲中,全部元信息都存儲在HiddenClass上的描述符數組中。
慢屬性存在於自包含的屬性字典中,再也不經過HiddenClass共享元信息。
慢屬性提供有效的屬性刪除和添加,但訪問速度比其餘兩種類型慢。
const o = ["a", "b", "c"]; console.log(o[1]); // Prints "b". delete o[1]; // Introduces a hole in the elements store. console.log(o[1]); // Prints "undefined"; property 1 does not exist. o.\_\_proto\_\_ = {1: "B"}; // Define property 1 on the prototype. console.log(o[0]); // Prints "a". console.log(o[1]); // Prints "B". console.log(o[2]); // Prints "c". console.log(o[3]); // Prints undefined
當有缺口的時候會在該位置打上the_hole標記表示不存在的屬性,能夠大大提升數組操做效率。
const sparseArray = []; sparseArray [9999] ='foo'; //建立一個包含字典元素的數組。
注意:只要使用自定義描述符定義索引屬性,V8就會轉向慢數組索引屬性:
const array = []; Object.defineProperty(array, 0, {value: "fixed", configurable: false}); console.log(array[0]); // Prints "fixed". array[0] = "other value"; // Cannot override index 0. console.log(array[0]); // Still prints "fixed".
refs:
http://www.javashuo.com/article/p-sscrflrf-h.html
https://v8project.blogspot.com/2017/08/fast-properties.html