摘要:也就是說,屬性控制了屬性描述對象的可寫性。可遍歷性返回一個布爾值,表示目標屬性是否可遍歷運算符不管某個屬性是對象自身的還是繼承的,都會返回。上面的寫法與定義屬性描述對象是等價的,而且使用更廣泛。
屬性描述對象
概述
Object.getOwnPropertyDescriptor()
Object.getOwnPropertyNames()
Object.defineProperty(),Object.defineProperties()
Object.prototype.propertyIsEnumerable()
元屬性
value
writable
enumerable
configurable
存取器
對象的拷貝
控制對象狀態
Object.preventExtensions()
Object.isExtensible()
Object.seal()
Object.isSealed()
Object.freeze()
Object.isFrozen()
局限性
1.概述
每個屬性都有自己對應的屬性描述對象,保存該屬性的一些元信息
{
value: 123,
writable: false,
enumerable: true,
configurable: false,
get: undefined,
set: undefined
}
屬性描述對象提供6個元屬性。
(1)value
value是該屬性的屬性值,默認為undefined。
(2)writable
writable是一個布爾值,表示屬性值(value)是否可改變(即是否可寫),默認為true。
(3)enumerable
enumerable是一個布爾值,表示該屬性是否可遍歷,默認為true。如果設為false,會使得某些操作(比如for...in循環、Object.keys())跳過該屬性。
(4)configurable
configurable是一個布爾值,表示可配置性,默認為true。如果設為false,將阻止某些操作改寫該屬性,比如無法刪除該屬性,也不得改變該屬性的屬性描述對象(value屬性除外)。也就是說,configurable屬性控制了屬性描述對象的可寫性。
(5)get
get是一個函數,表示該屬性的取值函數(getter),默認為undefined。
(6)set
set是一個函數,表示該屬性的存值函數(setter),默認為undefined。
2.Object.getOwnPropertyDescriptor()
Object.getOwnPropertyDescriptor()方法可以獲取屬性描述對象。它的第一個參數是目標對象,第二個參數是一個字符串,對應目標對象的某個屬性名。
Object.getOwnPropertyDescriptor()方法只能用于對象自身的屬性,不能用于繼承的屬性。
var obj = { p: "a" };
Object.getOwnPropertyDescriptor(obj, "toString")
// undefined
上面代碼中,toString是obj對象繼承的屬性,Object.getOwnPropertyDescriptor()無法獲取。
3.Object.getOwnPropertyNames()
Object.keys([]) // []
Object.getOwnPropertyNames([]) // [ "length" ]
Object.keys(Object.prototype) // []
Object.getOwnPropertyNames(Object.prototype)
// ["hasOwnProperty",
// "valueOf",
// "constructor",
// "toLocaleString",
// "isPrototypeOf",
// "propertyIsEnumerable",
// "toString"]
上面代碼中,數組自身的length屬性是不可遍歷的,Object.keys不會返回該屬性。第二個例子的Object.prototype也是一個對象,所有實例對象都會繼承它,它自身的屬性都是不可遍歷的。
4.Object.defineProperty(),
Object.defineProperty方法接受三個參數,依次如下。
object:屬性所在的對象
propertyName:字符串,表示屬性名
attributesObject:屬性描述對象
4.1Object.defineProperties()
var obj = {};
Object.defineProperty(obj, "p", {
value: 123,
get: function() { return 456; }
});
// TypeError: Invalid property.
// A property cannot both have accessors and be writable or have a value
Object.defineProperty(obj, "p", {
writable: true,
get: function() { return 456; }
});
// TypeError: Invalid property descriptor.
// Cannot both specify accessors and a value or writable attribute
4.1.2writable、configurable、enumerable這三個屬性的默認值都為false
4.1.1注意,一旦定義了取值函數get(或存值函數set),就不能將writable屬性設為true,或者同時定義value屬性,否則會報錯。
5.Object.prototype.propertyIsEnumerable()
這個方法只能用于判斷對象自身的屬性,對于繼承的屬性一律返回false
var obj = {};
obj.p = 123;
obj.propertyIsEnumerable("p") // true
obj.propertyIsEnumerable("toString") // false
上面代碼中,obj.p是可遍歷的,而obj.toString是繼承的屬性
6.元屬性
6.1value
value屬性是目標屬性的值。
var obj = {};
obj.p = 123;
Object.getOwnPropertyDescriptor(obj, "p").value
// 123
Object.defineProperty(obj, "p", { value: 246 });
obj.p // 246
上面代碼是通過value屬性,讀取或改寫obj.p的例子
6.2
writable屬性是一個布爾值,決定了目標屬性的值(value)是否可以被改變
6.2.1如果原型對象的某個屬性的writable為false,那么子對象將無法自定義這個屬性。
var proto = Object.defineProperty({}, "foo", {
value: "a",
writable: false
});
var obj = Object.create(proto);
obj.foo = "b";
obj.foo // "a"
上面代碼中,proto是原型對象,它的foo屬性不可寫。obj對象繼承proto,也不可以再自定義這個屬性了。如果是嚴格模式,這樣做還會拋出一個錯誤。
6.3enumerable
6.3.1enumerable(可遍歷性)返回一個布爾值,表示目標屬性是否可遍歷
6.3.2in運算符不管某個屬性是對象自身的還是繼承的,都會返回true。
后來就引入了“可遍歷性”這個概念。只有可遍歷的屬性,才會被for...in循環遍歷,同時還規定toString這一類實例對象繼承的原生屬性,都是不可遍歷的,這樣就保證了for...in循環的可用性。
6.3.3具體來說,如果一個屬性的enumerable為false,下面三個操作不會取到該屬性。
for..in循環
Object.keys方法
JSON.stringify方法
object.getpropertynames都可以遍歷。
6.3.4用于保密屬性
JSON.stringify方法會排除enumerable為false的屬性,有時可以利用這一點。如果對象的 JSON 格式輸出要排除某些屬性,就可以把這些屬性的enumerable設為false。
6.4configurable
onfigurable為false時,value、writable、enumerable和configurable都不能被修改了
var obj = Object.defineProperty({}, "p", {
value: 1,
writable: false,
enumerable: false,
configurable: false
});
Object.defineProperty(obj, "p", {value: 2})
// TypeError: Cannot redefine property: p
Object.defineProperty(obj, "p", {writable: true})
// TypeError: Cannot redefine property: p
Object.defineProperty(obj, "p", {enumerable: true})
// TypeError: Cannot redefine property: p
Object.defineProperty(obj, "p", {configurable: true})
// TypeError: Cannot redefine property: p
上面代碼中,obj.p的configurable為false。然后,改動value、writable、enumerable、configurable,結果都報錯。
6.4.1注意,writable只有在false改為true會報錯,true改為false是允許的
6.4.2至于value,只要writable和configurable有一個為true,就允許改動
6.4.3可配置性決定了目標屬性是否可以被刪除(delete)
6.5存取器
var obj = Object.defineProperty({}, "p", {
get: function () {
return "getter";
},
set: function (value) {
console.log("setter: " + value);
}
});
obj.p // "getter"
obj.p = 123 // "setter: 123"
上面代碼中,obj.p定義了get和set屬性。obj.p取值時,就會調用get;賦值時,就會調用set。
JavaScript 還提供了存取器的另一種寫法。
var obj = {
get p() {
return "getter";
},
set p(value) {
console.log("setter: " + value);
}
};
上面的寫法與定義屬性描述對象是等價的,而且使用更廣泛。
6.5.1應用
存取器往往用于,屬性的值依賴對象內部數據的場合。
var obj ={
$n : 5,
get next() { return this.$n++ },
set next(n) {
if (n >= this.$n) this.$n = n; else throw new Error("新的值必須大于當前值");
}
};
obj.next // 5
obj.next = 10;
obj.next // 10
obj.next = 5;
// Uncaught Error: 新的值必須大于當前值
上面代碼中,next屬性的存值函數和取值函數,都依賴于內部屬性$n。
7.對象的拷貝
var extend = function (to, from) {
for (var property in from) {
to[property] = from[property];
}
return to;
}
extend({}, {
a: 1
})
// {a: 1}
7.1上面這個方法的問題在于,如果遇到存取器定義的屬性,會只拷貝值。
extend({}, {
get a() { return 1 }
})
// {a: 1}
為了解決這個問題,我們可以通過Object.defineProperty方法來拷貝屬性。
var extend = function (to, from) {
for (var property in from) {
if (!from.hasOwnProperty(property)) continue; Object.defineProperty( to, property, Object.getOwnPropertyDescriptor(from, property) );
}
return to;
}
extend({}, { get a(){ return 1 } })
// { get a(){ return 1 } })
上面代碼中,hasOwnProperty那一行用來過濾掉繼承的屬性,否則可能會報錯,因為Object.getOwnPropertyDescriptor讀不到繼承屬性的屬性描述對象。
8.控制對象狀態
有時需要凍結對象的讀寫狀態,防止對象被改變。JavaScript 提供了三種凍結方法,最弱的一種是Object.preventExtensions,其次是Object.seal,最強的是Object.freeze
8.1Object.preventExtensions()
無法增加屬性
var obj = new Object();
Object.preventExtensions(obj);
Object.defineProperty(obj, "p", {
value: "hello"
});
// TypeError: Cannot define property:p, object is not extensible.
obj.p = 1;
obj.p // undefined
Object.isExtensible()
8.2Object.seal()
無法增刪屬性
8.2.1Object.seal實質是把屬性描述對象的configurable屬性設為false,因此屬性描述對象不再能改變了
var obj = {
p: "a"
};
// seal方法之前
Object.getOwnPropertyDescriptor(obj, "p")
// Object {
// value: "a",
// writable: true,
// enumerable: true,
// configurable: true
// }
Object.seal(obj);
// seal方法之后
Object.getOwnPropertyDescriptor(obj, "p")
// Object {
// value: "a",
// writable: true,
// enumerable: true,
// configurable: false
// }
Object.defineProperty(o, "p", {
enumerable: false
})
// TypeError: Cannot redefine property: p
上面代碼中,使用Object.seal方法之后,屬性描述對象的configurable屬性就變成了false,然后改變enumerable屬性就會報錯
8.2.2Object.seal只是禁止新增或刪除屬性,并不影響修改某個屬性的值。
var obj = { p: "a" };
Object.seal(obj);
obj.p = "b";
obj.p // "b"
上面代碼中,Object.seal方法對p屬性的value無效,是因為此時p屬性的可寫性由writable決定。
Object.isSealed()
8.3Object.freeze()
使得這個對象實際上變成了常量
無法增刪改屬性
使用Object.freeze方法以后,Object.isSealed將會返回true,Object.isExtensible返回false
Object.isFrozen()
Object.isFrozen的一個用途是,確認某個對象沒有被凍結后,再對它的屬性賦值。
var obj = {
p: "hello"
};
Object.freeze(obj);
if (!Object.isFrozen(obj)) {
obj.p = "world";
}
9.局限性
9.1可以通過改變原型對象,來為對象增加屬性
9.1.1一種解決方案是,把obj的原型也凍結住。
var obj = new Object();
Object.preventExtensions(obj);
var proto = Object.getPrototypeOf(obj);
Object.preventExtensions(proto);
proto.t = "hello";
obj.t // undefined
9.2如果屬性值是對象,上面這些方法只能凍結屬性指向的對象,而不能凍結對象本身的內容
var obj = {
foo: 1,
bar: ["a", "b"]
};
Object.freeze(obj);
obj.bar.push("c");
obj.bar // ["a", "b", "c"]
上面代碼中,obj.bar屬性指向一個數組,obj對象被凍結以后,這個指向無法改變,即無法指向其他值,但是所指向的數組是可以改變的
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/105896.html
摘要:也就是說,屬性控制了屬性描述對象的可寫性。可遍歷性返回一個布爾值,表示目標屬性是否可遍歷運算符不管某個屬性是對象自身的還是繼承的,都會返回。上面的寫法與定義屬性描述對象是等價的,而且使用更廣泛。 屬性描述對象 概述Object.getOwnPropertyDescriptor()Object.getOwnPropertyNames()Object.defineProperty(),Ob...
摘要:出現的目的同一樣也是要提到頁面中的腳本代碼。標準標準標簽庫有個子庫,但隨著發展,目前常使用的是他的核心庫標簽庫標簽庫的前綴下載與導入下載從的網站下載的包。 一、JSP技術1.jsp腳本和注釋jsp腳本:1) ----- 內部的java代碼翻譯到service方法的內部2) ----- 會被翻譯成service方法內部out.print()3) ---- 會被翻譯成servlet的成員的...
摘要:退出運行時上下文并返回一個布爾值旗標來表明所發生的任何異常是否應當被屏蔽。除了實現上下文管理協議以外,不同類型不會被特殊處理。其中一些并不會被內置函數所列出。 上一篇文章:Python標準庫---15、內置類型:集合類型、映射類型下一篇文章:Python標準庫---17、內置異常 上下文管理器類型 Python 的 with 語句支持通過上下文管理器所定義的運行時上下文這一概念。 此...
閱讀 2570·2021-09-06 15:02
閱讀 3200·2021-09-02 10:18
閱讀 2822·2019-08-30 15:44
閱讀 685·2019-08-30 15:43
閱讀 1948·2019-08-30 14:08
閱讀 2758·2019-08-30 13:16
閱讀 1397·2019-08-26 13:52
閱讀 931·2019-08-26 12:21