Javascript Object.defineProperty()

zuo發表於2014-10-27

轉載宣告:

本文標題: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方法的描述,文中不妥之處,還望批評指正。

相關文章