属性的标志
对象属性除value外还有三个特殊属性,即标志
writable ----如果为true,则可以修改,否则它只是只读的。
enumerable ----如果为true,则可在循环中列出,否则不列出。
configurable -----如果为true,则此属性可以被删除,相应的特性也可以被修改,否则不可以
得到这些标志的语法:
let descriptor = Object.getOwnPropertyDescriptor(obj,propertyName);
obj 需要获取信息的对象
propertyName 属性的名称
let user = {
name : "Jhon"
};
let descriptor = Object.getOwnPropertyDescriptor(user,‘name‘);
alert(JSON.stringify(descriptor,null,2));
/* property descriptor:
{
"value": "John",
"writable": true,
"enumerable": true,
"configurable": true
}
*/
标志修改语法:Object.defineProperty(obj,propertyName,descriptor)
1 let user = {}; 2 3 Object.defineProperty(user, "name", { 4 value: "John" 5 }); 6 7 let descriptor = Object.getOwnPropertyDescriptor(user, ‘name‘); 8 9 alert( JSON.stringify(descriptor, null, 2 ) ); 10 /* 11 { 12 "value": "John", 13 "writable": false, 14 "enumerable": false, 15 "configurable": false 16 } 17 */
设置属性只读
let user = {
name : "Jhon"
};
Object.defineProperty(user,"name",{
writable:false
});
user.name = "XiaoMing";//错误,不能设置只读属性‘name’;
不可枚举
通过设置 enumerable 标志可以设置属性是否可以枚举
1 let user = { 2 name: "John", 3 toString() { 4 return this.name; 5 } 6 }; 7 8 // 默认情况下,我们的两个属性都会列出: 9 for (let key in user) alert(key); // name, toString 10 11 12 Object.defineProperty(user, "toString", { 13 enumerable: false 14 }); 15 16 // 现在 toString 消失了: 17 for (let key in user) alert(key); // name
不可配置
通过设置configurable 标志,来控制属性是否可以修改
1 let user = { }; 2 3 Object.defineProperty(user, "name", { 4 value: "John", 5 writable: false, 6 configurable: false 7 }); 8 9 // 不能修改 user.name 或 它的标志 10 // 下面的所有操作都不起作用: 11 // user.name = "Pete" 12 // delete user.name 13 // defineProperty(user, "name", ...) 14 Object.defineProperty(user, "name", {writable: true}); // 错误
Object.defineProperties
一次定义多个属性,语法和示例如下:
1 Object.defineProperties(obj, { 2 prop1: descriptor1, 3 prop2: descriptor2 4 // ... 5 }); 6 Object.defineProperties(user, { 7 name: { value: "John", writable: false }, 8 surname: { value: "Smith", writable: false }, 9 // ... 10 });
Object.getOwnPropertyDescriptors(obj)
一次获取所有属性描述
语法:let
clone =
Object.
defineProperties
(
{
}
,
Object.
getOwnPropertyDescriptors
(
obj)
)
;
getter 和 setter
1 2 let obj = { 3 get propName() { 4 // getter, the code executed on getting obj.propName 5 }, 6 7 set propName(value) { 8 // setter, the code executed on setting obj.propName = value 9 } 10 };
访问器描述符
get
—— 一个没有参数的函数,在读取属性时工作,set
—— 带有一个参数的函数,当属性被设置时调用,enumerable
—— 与数据属性相同,configurable
—— 与数据属性相同。兼容性
1 function User(name, birthday) { 2 this.name = name; 3 this.birthday = birthday; 4 5 // age 是由当前日期和生日计算出来的 6 Object.defineProperty(this, "age", { 7 get() { 8 let todayYear = new Date().getFullYear(); 9 return todayYear - this.birthday.getFullYear(); 10 } 11 }); 12 } 13 14 let john = new User("John", new Date(1992, 6, 1)); 15 16 alert( john.birthday ); // birthday 是可访问的 17 alert( john.age ); // ...age 也是可访问的
这个例子主要解决了,当存储表示一个可以互相转换的值。
Prototype
Prototype 是内部隐藏的,但是可以通过_proto_设置
let animal = {
eats:true
};
let rabbit = {
jumps:true
};
rabbit._proto_=animal;
alert(rabbit.eats);
alert(rabbit.jumps);
F.prototype
属性与 [[Prototype]]
不同。F.prototype
唯一的作用是:当 new F()
被调用时,它设置新对象的 [[Prototype]]
。F.prototype
的值应该是一个对象或 null:其他值将不起作用。"prototype"
属性在设置为构造函数时仅具有这种特殊效果,并且用 new
调用。
1 let animal = { 2 eats: true 3 }; 4 5 function Rabbit(name) { 6 this.name = name; 7 } 8 9 Rabbit.prototype = animal; 10 11 let rabbit = new Rabbit("White Rabbit"); // rabbit.__proto__ == animal 12 13 alert( rabbit.eats ); // true
Array.prototype
、Object.prototype
、Date.prototype
等)。Number.prototype
、String.prototype
和 Boolean.prototype
。只有 undefined
和 null
没有包装对象。proto
作为 [[Prototype]]
来创建一个空对象。obj
的 [[Prototype]]
(和 __proto__
getter 相同)。obj
的 [[Prototype]]
设置为 proto
(和 __proto__
setter 相同)。obj
拥有名为 key
的自身属性(非继承得来),返回 true
。 同时我们还明确了 __proto__
是 [[Prototype]]
的 getter/setter,位置在 Object.prototype
,和其他方法相同。
我们可以不借助 prototype 创建一个对象,那就是 Object.create(null)
。这些对象被用作是「纯字典」,对于它们而言 "__proto__"
作为键没有问题。
所有返回对象属性的方法(如 Object.keys
以及其他)—— 都返回「自身」属性。如果我们想继承它们,我们可以使用 for...in
。
原文:https://www.cnblogs.com/xiaoqiyaozou/p/11495930.html