轉載宣告:
本文標題:Javascript Object.defineProperty()
本文連結:http://www.zuojj.com/archives/994.html,轉載請註明轉自Benjamin-專注前端開發和使用者體驗
Javascript作為一種語言,有個美譽,開發者可以重新定義任何事情。雖然這在過去的一些javascript可以,但是ECMAScript5中已經開始得到改變,例如,我們可以使用Object.defineProperty建立一個不能被修改的物件的屬性。本文中我們將講述Object.defineProperty的基本用法。 如果你想在文章開始之前,深入瞭解Object.defineProperty方法,請戳。
一、基本用法
假如我想構建一個math.js庫,看下面的例項:
var mathObj = { constants: { "pi": 3.14 }, areaOfCircle: function(radius) { return this.constants.pi*radius*radius; } }
在上例中,如果有人改變pi的值,那麼我們將不會得到正確的計算結果,雖然有很多方法可以解決此問題,但是最簡單的方法是使用pi屬性不可寫。看下面例項:
var mathObj = { constants: {}, areaOfCircle: function(radius) { return this.constants.pi*radius*radius; } } Object.defineProperty(mathObj.constants, "pi", { value: 3.14, writable: false }); mathObj.constants.pi = "Benjamin"; //Outputs: 3.14 console.log(mathObj.constants.pi);
Object.defineProperty(obj, prop, descriptor)方法接收三個引數:需要新增或修改屬性的物件,屬性名稱,屬性描述options。從上例可以看出,當給pi賦值為“Benjamin”時,最後輸出的值還是3.14。 但是如果給math.js使用“use strict",將會報錯,和給undefined賦值一樣:
"use strict";
var mathObj = {
constants: {},
areaOfCircle: function(radius) {
return this.constants.pi*radius*radius;
}
}
Object.defineProperty(mathObj.constants, "pi", {
value: 3.14,
writable: false
});
mathObj.constants.pi = "Benjamin";
//Outputs: Uncaught TypeError: Cannot assign to read only property 'pi' of #<Object>
console.log(mathObj.constants.pi);
第三個引數的options中,writable預設值為false,所以在上例中可以省略,configurable預設值為false,如果你想使用你的庫的使用者故意重寫pi的值,你可以設定configurable值為true。
Object.defineProperty(principia.constants, "pi", { value: 3.14, configurable: true });
但是當你使用Object.defineProperty時,也有一種相當大的Hack,即使設定了writable的值,它也不會保持屬性值不變的:
var container = {}; Object.defineProperty(container, "arr", { writable: false, value: ["a", "b"] }); container.arr = ["new array"]; // Outputs: ["a", "b"] console.log(container.arr); container.arr.push("new value"); // Outputs: ["a", "b", "new value"] console.log(container.arr);
arr陣列是不可寫的,所以始終指向同一個陣列,但是陣列的成員是可以變化的,所以將來可能會增加鎖定陣列或者物件來解決此問題。
二、相容性
因為Object.defineProperty方法是ES5的一部分,所以在IE9及現代瀏覽器,IE8中只得到了部分實現,儘可以使用在DOM物件上,不幸的是,並沒有IE8相關的shim來相容。但是,如果你不需要處理舊的瀏覽器,defineProperty可能會有你使用的地方。 以上就是對Object.defineProperty方法的描述,文中不妥之處,還望批評指正。