它是一个函数,在执行的时候小括号里放了一堆东西,还有个对象,一度我对它是个什么有了疑问。后台打印一下,放心了,它就是个函数,一个方法,JS底层的一个方法(函数)只供浏览器使用,在es5开放给了开发者。
实际上,它们还叫做API,API的英文全称(Application Programming Interface),虽然API也是函数,它还是有些特殊性的。
它的参数里的对象,就是被叫做属性描述符的。有的资料把它们叫做 属性的属性。我倒觉得它更好理解,属性的属性。
这个对象有两个写法
数据属性
数据属性(data property)包含一个数据值的位置,在这个位置可以读取和写入值。数据属性有4个特性
【1】Configurable(可配置性)
可配置性决定是否可以使用delete删除属性,以及是否可以修改属性描述符的特性,默认值为true
【2】Enumerable(可枚举性)
可枚举性决定属性是否出现在对象的属性枚举中,比如是否可以通过for-in循环返回该属性,默认值为true
【3】Writable(可写性)
可写性决定是否可以修改属性的值,默认值为true
【4】Value(属性值)
属性值包含这个属性的数据值,读取属性值的时候,从这个位置读;写入属性值的时候,把新值保存在这个位置。默认值为undefined
或者写作:get方法和set方法,这时,没有Writable和value两个属性。它们两组是互相替换的。
get是一个隐藏函数,在获取属性值时调用。set也是一个隐藏函数,在设置属性值时调用,它们的默认值都是undefined。Object.definedProperty()中的get和set对应于对象字面量中get和set方法
[注意]getter和setter取代了数据属性中的value和writable属性
== 描述符方法 ==
前面介绍了属性描述符,要想设置它们,就需要用到描述符方法。描述符方法总共有以下4个:
【1】Object.getOwnPropertyDescriptor()
Object.getOwnPropertyDescriptor(o,name)方法用于查询一个属性的描述符,并以对象的形式返回
查询obj.a属性时,可配置性、可枚举性、可写性都是默认的true,而value是a的属性值1
查询obj.b属性时,因为obj.b属性不存在,该方法返回undefined
var obj = {a:1};
//Object {value: 1, writable: true, enumerable: true, configurable: true}
console.log(Object.getOwnPropertyDescriptor(obj,'a'));
//undefined
console.log(Object.getOwnPropertyDescriptor(obj,'b'));
【2】Object.defineProperty()
Object.defineProperty(o,name,desc)方法用于创建或配置对象的一个属性的描述符,返回配置后的对象
使用该方法创建或配置对象属性的描述符时,如果不针对该属性进行描述符的配置,则该项描述符默认为false
var obj = {};
//{a:1}
console.log(Object.defineProperty(obj,'a',{
value:1,
writable: true
}));
//由于没有配置enumerable和configurable,所以它们的值为false
//{value: 1, writable: true, enumerable: false, configurable: false}
console.log(Object.getOwnPropertyDescriptor(obj,'a'));
【3】Object.defineProperties()
Object.defineProperty(o,descriptors)方法用于创建或配置对象的多个属性的描述符,返回配置后的对象
var obj = {
a:1
};
//{a: 1, b: 2}
console.log(Object.defineProperties(obj,{
a:{writable:false},
b:{value:2}
}));
//{value: 1, writable: false, enumerable: true, configurable: true}
console.log(Object.getOwnPropertyDescriptor(obj,'a'));
//{value: 2, writable: false, enumerable: false, configurable: false}
console.log(Object.getOwnPropertyDescriptor(obj,'b'));
【4】Object.create()
Object.create(proto,descriptors)方法使用指定的原型和属性来创建一个对象
var o = Object.create(Object.prototype,{
a:{writable: false,value:1,enumerable:true}
});
//{value: 1, writable: false, enumerable: true, configurable: true}
console.log(Object.getOwnPropertyDescriptor(obj,'a'));
对象属性的特性
- ECMAScript 中有一个名为“属性描述符”(property descriptor)的对象
- 这个属性描述符对象{ },就是属性的属性,用于描述属性的行为特性。
- ECMA-262 定义这些特性是为了实现JavaScript引擎用到,因此在JavaScript中不能直接访问它们。为了表示特性的内部值,该规范把它们放在了两对方括号中,eg. [[Enumerable]]。
读取属性的特性
- getOwnPropertyDescriptor() 方法 返回指定对象上自有属性对应的属性描述符。
- Object.getOwnPropertyDescriptor(obj, prop)
- obj-需要查找的目标对象 prop- 目标对象内属性名称
数据描述符 - 数据属性
特性名称 | 描述 | 默认值 |
---|---|---|
cofigurable | 当且仅当该属性的值为true时,该属性描述符才能够被改变,同时该属性也能从对应对象上被删除 | FALSE |
enumerable | 是否可枚举属性:true 可枚举,可通过for···in···语句枚举属性;false 不可枚举 | FALSE |
value | 该属性对应的值。可以是任何有效的JavaScript值(数值,对象,函数等) | FALSE |
writable | 当且仅当该属性的writable为true时,value才能被赋值运算符改变 | FALSE |
1) 在使用Object.defineProperty、 Object.defineProperties或Object.create函数的情况下添加数据属性,writable、enumerable和configurable默认值为false。
2)使用对象字面量创建的属性,writable、enumerable和configurable默认值为true。
如何修改属性默认的特性
Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回这个对象。
Object.defineProperty(obj, prop, descriptor)
三个参数:属性所在对象,属性名称,描述符对象。
该方法允许精确添加或修改对象的属性。默认情况下,使用Object.defineProperty()添加的属性值是不可修改的
存取描述符 - 访问器属性
特性名称 | 描述 | 默认值 |
---|---|---|
cofigurable | 当且仅当该属性的值为true时,该属性描述符才能够被改变,同时该属性也能从对应对象上被删除 | FALSE |
enumerable | 是否可枚举属性:true 可枚举,可通过for···in···语句枚举属性;false 不可枚举 | FALSE |
get | 一个给属性提供getter的方法。当访问该属性时,该方法会被执行,方法执行时没有参数传入,但是会传入this对象 | FALSE |
set | 一个给属性提供setter的方法,如果没有setter则为undefined。当属性值修改时,触发执行该方法。该方法将接受唯一参数,即该属性新的参数值。 | FALSE |
访问器属性不能直接定义,必须使用Object.defineProperty()来定义。
如果一个描述符不具有value,writable,get和set任意一个关键字,那么它被认为是一个数据描述符。如果一个描述符同时有(value或writable)和(get或set)关键字,将会产生一个异常
定义多个属性
Object.defineProperties(obj, props)
利用这个方法可直接在一个对象上定义多个新的属性或修改多个现有属性,并返回该对象。第一个参数,要修改或定义属性的对象;第二个参数,是一个映射表,它包含要新建或修改的属性名称,和它们对应的属性描述符对象
定义属性特性时需要注意的几个问题
- 如果对象是不可扩展的,则只可以编辑已有的自有属性,不能为其新增属性;
- 如果属性是不可配置的,则不能修改它的可配置性和可枚举性;
- 如果存储器属性是不可配置的,则不能修改其getter和setter方法,也不能把它转换为数据属性;
- 如果数据属性是不可配置的,则不能将其转换为存储器属性,也不能将其从false改写为true,但可以从true改写为false;
- 如果数据属性是不可配置也不可写,则不能修改它的值。然而可配置但不可写的值是可以修改的(实际上是将其先配置为可写的,然后再修改它的值,最后转换为不可写的)