属性描述符(元属性)
含义:对象的属性的属性(可读,可写,可更改),也可以称之为 对象的属性的属性描述符。
- 属性描述符:
Object.getOwnPropertyDescriptor(obj,"name");
第一个参数:对应的对象
第二个参数:对应对象的属性
返回得到的值,为这个对象属性的属性状态 writable,enumberable,configurable,value
- writable:可读写+value(写在对象中)
- enumberable:可枚举
表示属性能不能出现在对象的for in循环中
- configurable :可配置
可用来重定义
为对象新增或修改属性
- 使用字面量定义对象,属性描述符的默认值都是true
var obj={
name:"snw"
};
//获取对象属性的属性
var result = Object.getOwnPropertyDescriptor(damu,"wife");
console.log(result);
//返回值为
configurable:true
enumerable:true
value:"snw"
writable:true
- 使用定义属性的方法,属性描述符的默认值都是false
Object.defineProperty(对象,"对象的属性",{
value:"xiaohua" //属性值
<!--可定义属性的属性状态-->
})
var result = Object.getOwnPropertyDescriptor(llc,"wife");
console.log(result);
//返回值为
configurable:false
enumerable:false
value:"snw"
writable:false
- 使用var定义和没有使用var定义的属性描述符,的区别就是使用var定义configurable:false
var a =2;
b=3;
var result1 = Object.getOwnPropertyDescriptor(window,"a");
//它的返回值中configurable:false,其余的都是true
console.log(result1);
var result2 = Object.getOwnPropertyDescriptor(window,"b");
//它的返回值属性描述符全都是true
console.log(result2);
- writable
当writable为false时,对应的属性的值是无法修改的。
在默认情况下:
继续修改的话会静默失败
在严格模式下(“use strict”):
会报错 - configurable来决定属性是否可以配置
当configurable为false时,对应的属性是无法重新定义和无法删除的。但该对象是还可以继续添加属性的。不管是默认情况还是严格模式底下,进行重新定义和删除都会报错
- 注意一个小小的例外:
当configurable为false时,writable可以进行重新定义,但只满足由writable:true ==> writable:false
configurable:不能修改
enumerable:不能修改
- 注意一个小小的例外:
- enumerable 枚举(可遍历)
Object.defineProperty(obj,"a",{
//将属性a设置为可以枚举的对象
enumerable:true
})
//判断这个对象的属性是否可枚举,返回值为ture/false
对象.propertyIsEnumerable("属性"));不会遍历原型链
//将对象中可以枚举的属性,全都输出
Object.keys(对象);不会遍历原型链
//将对象中的属性全都输出
Object.getOwnPropertyNames(对象);不会遍历原型链
- 对象常量属性
将属性的writable和configurable设置为false
但在这个情况下,虽然不能配置和修改,但是还可以增加新的属性。 - 禁止对象扩展
Object.preventExtensions(obj);
由于属性描述符是对属性的管理,所以想禁止对象扩展不能使用属性描述符来控制,而是需要调用Object.preventExtensions(obj);
参数(obj):要求禁止扩展的对象
默认情况下:
为对象添加新的属性会静默失败
严格模式底下:报错
* 注意:禁止对象扩展只是禁止了对象去扩展属性,而之前的属性是可以进行重新定义或者删除的,属性值也是可以修改的。
- 密封对象(也可以禁止对象扩展)
Object.seal(obj)
在禁止对象扩展(Object.preventExtensions(obj);的基础上把现有属性的configurable调整为false
调用Object.seal(obj)密封一个对象
密封之后禁止了对象去扩展属性,原有的属性不可以进行重新定义或者删除,但属性值是可以修改的
- 冻结对象(也可以禁止对象扩展)
Object.freeze(obj)
在密封对象(Object.seal(obj))的基础上把现有属性的writable调整为false
调用Object.freeze(obj)密封一个对象
冻结之后禁止了对象去扩展属性,原有的属性不可以进行重新定义或者删除,属性值也不可以进行修改
- 注意:在js中,所有方法的创建都是浅不变形的,他们只会影响目标对象和他的直接属性。只能影响对象的直接属性。没有办法作用到对象的深层属性,没有办法作用到对象隐式原型链上的属性
例如:
var obj={
arr:{
num1:1,
num2:2,
num3:3
}
};
/*Js操作的对象都是他的目标对象和直接属性,当密封
和冻结这个对象的时候,只是对直接属性arr做的操作,
num的属性还是可以操作*/
- 有length属性的均为伪数组
//创建一个长度为3的伪数组
var arr={length:3,
num1:1,
num2:2,
num3:3
}
- 将伪数组转变为数组
var arr =Array.prototype.slice.call(伪数组名);或
var arr =[].slice.call(伪数组名);
- 属性
- 属性描述符:描述属性的属性(元属性)
- 数据描述符:带有value和writable属性描述符的属性
- 访问描述符:带有set和get属性描述符的属性,对于访问描述符来说,Javascript会忽略他们的value和writable特性。取而代之的是set和get
具有set和get属性描述符的属性我们称为访问描述符
作用:
使用属性的操作更安全可控(封装)
函数。
存在性检查
in操作符:会遍历原型链
obj.hasOwnProperty(“a):不会遍历原型链,只在对象中查找
- 属性的查找 get属性查找的算法
1,在对象中查找是否具有相同名称的属性,如果找到了,就会返回这个属性的值。
2,如果没有找到,则遍历原型链
3,无论·如何都没找到,返回undefined
- 注意点:如果是访问描述符,就看get函数,返回的值为get函数中的相关内容。
- 属性的设置 put属性设置的算法
- 如果属性直接存在于对象中,不在原型链上
找到直接存在于对象中的属性
- 数据描述符(没有setter/getter):
直接修改对象中的属性(注意writbale的值) - 访问描述符:
直接调用set方法
- 数据描述符(没有setter/getter):
- 如果属性直接存在于对象中 , 也在原型链上
找到直接存在于对象中的属性
- 数据描述符(没有setter/getter):
直接修改对象中的属性(注意writbale的值) - 访问描述符
直接调用set方法
- 数据描述符(没有setter/getter):
- 如果属性不直接存在于对象中也不在原型链上
在对象的直接属性中添加一个属性(数据描述符)默认情况下,它的属性描述符都是true
- 如果属性直接存在于对象中,不在原型链上
value:"a"
writable:true
configurable:true
enumerable:true
-
- 如果属性不直接存在于对象中 , 在原型链上
- 该属性(原型链)是数据描述符(没有setter/getter)
- writbale为true:
直接在对象中添加一个属性,我们称之为屏蔽属性 - writbale为false:
不会生成屏蔽属性
- writbale为true:
- 该属性(原型链)是数据描述符(没有setter/getter)
- 如果属性不直接存在于对象中 , 在原型链上
Object.prototype.age=10;
/*原型对象默认情况下都是true,将对象中的属性进行了重新定义*/
Object.defineProperty(Object.prototype,"age",{
writable:false
});
console.log(Object.getOwnPropertyDescriptor(Object.prototype,"age"));
var obj={};
/*当都为true时,可以向对象中添加数据;
当writable:false时,添加不上属性,添加属性的语句会静默失败*/
obj.age=50;//静默失败
console.log(obj);
console.log(Object.prototype);
-
- 该属性是访问描述符
调用set,不会生成屏蔽属性
当有get时,才会向对象中添加属性。
- 该属性是访问描述符
-