一、背景原因
原文报错:
Uncaught TypeError: Property description must be an object: a
at Function.defineProperties (<anonymous>)
未捕获的类型错误:属性描述必须是一个对象:。。。
背景:
使用Object.defineProperty()方法时,不小心通过快捷键按倒了Object.defineProperties()方法。
原因:
其实也就是Object.defineProperty()方法与Object.defineProperties()方法的用法差异。下面针对这2个方法说明下。
二、Object.defineProperty()
1、概述:
该静态方法用于给对象定义一个新的属性,或修改一个现有属性,其格式为:
Object.defineProperty(obj, prop, descriptor)
参数解析:
·obj:需要定义属性的对象、被操作对象;
·prop:需要定义或修改的属性名称,通常使用’’单引号括住;
·descriptor:要定义或修改的属性的描述符。
方法返回值:所传入的对象obj,并且指定新增或修改的属性已经被操作完成。
2、简单代码示例:
/** Object.defineProperty()的用法 **/
//新建一个对象
let person = {
name:'刘亦菲',
sex:'女'
};
//通过defineProperty方法对上述对象进行新属性age的插入
Object.defineProperty(person, 'age',{
value : '18'
});
//打印对象
console.log(person);
3、结果呈现:
4、描述符:
1)描述符概念与作用:
·Object.defineProperty()允许精确的添加或修改对象上的属性。
·通过赋值添加的普通属性会在枚举属性时出现(例如for..in、Object.keys()等),它们的值可以被更改,也可以被删除;
·但是,当使用Object.defineProperty()操作属性时,属性的额外细节将会被修改,令其与默认值不同。通过该新增的属性在默认情况下,是不可写、不可枚举(即遍历等)、不可配置的。
·Object.defineProperty()使用[[defineOwnProperty]]内部方法,而不是[[Set]],即使属性已经存在,它也不会调用setter。
2)描述符类型:
对象中存在的属性描述符主要有两种类型:描述符只能是两种类型之一,不能同时为两者。
a、数据描述符;
数据描述符是一个具有可写或不可写值的属性。
b、访问器描述符。
访问器描述符是由getter/setter函数对描述的属性。
3)描述符可选键:
共享描述符:(即数据描述符、访问器描述符皆具备的键)
a、configurable:默认false
·用于指定属性的类型能否在数据属性、访问器属性之间更改;默认否。
·指定属性是否可被删除;默认否。
·指定其描述符的其他属性能否更改。默认否(当它是可写的数据描述符时,value键可以被改,writable可以改为false)
b、enumerable:默认false
控制当前操作的属性,能否被枚举。当且仅当该属性在对象的属性枚举中出现时,值为true。
数据描述符特有键:
a、value:默认undefined(未定义、未明确的)
配置属性的值。可以是任何有效的js值(数字、对象、函数等)。
b、writable:默认false
是否可写。需要配置与属性关联的值,可以使用赋值运算符更改,则为true。
访问器描述符特有键:
a、get:默认undefined
·用于属性getter的函数,没有getter则为undefined
·访问该属性时,将不带参地调用此函数,并将this设置为通过该属性访问的对象。
·返回值将被用作该属性的值。
b、set:默认undefined
·用作属性setter的函数,没有setter则为undefined
·当属性被赋值时,将调用该函数,并带一个参数(需要赋予属性的值),并将this设置为通过该属性分配的对象。
5、描述符的要点:
1)如果描述符没有value、writable、get和set键的任何一个,默认视为数据描述符。即如果你使用了Object.defineProperty()方法,操作一个对象,而不对描述符进行键配置。默认就是数据描述符。
2)如果描述符同时具备两种类型的描述符键,则会抛出异常。(即同时具备了value\writable和get\set)。
3)这些属性不一定是描述符本身的属性。继承的属性也会被考虑在内。为了确保这些默认值得到保留,你可以预先冻结描述符对象原型链中的现有对象,明确指定所有选项,或使用 Object.create(null) 指向 null。
三、Object.defineProperties()
1、概述:
这个函数的作用与描述符的概念,跟上面的Object.defineProperty()是一致的。唯一不同的是使用格式。可以理解为,Object.defineProperty()可以操作对象的一个属性,而Object.defineProperties()可以操作对象的多个属性。
2、格式:
Object.defineProperties(obj, props)
·obj:需要操作的对象;
·props:需要操作的属性组,可以是一个或多个
-- props的格式一般为map类型,如:
Object.defineProperties(obj, {
property1: {
value: true,
writable: true,
},
property2: {
value: "Hello",
writable: false,
},
// ……
});
3、代码示例:同时演示键enumerable的作用(枚举)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8 /">
<title>数据代理</title>
<script type="text/javascript" src=""></script>
</head>
<body>
<script type="text/javascript">
/** Object.defineProperty()的用法 **/
//新建一个对象
let person = {
name:'刘亦菲',
sex:'女'
};
//通过defineProperty方法对上述对象进行新属性age的插入
Object.defineProperty(person, 'age',{
value : 18
});
//打印对象
console.log(person);
/** Object.defineProperties()的用法 **/
//新建一个对象
let student = {
name:'张柏芝',
sex:'女'
};
//通过defineProperty方法对上述对象进行新属性age的插入
Object.defineProperties(student,{
'age':{
value:20,
enumerable:true
},
'adress':{
value:'五环'
}
});
//打印对象
console.log(student);
//枚举测试:
console.log('枚举测试:',Object.keys(student));
</script>
</body>
</html>
分析:
1)在页面展示中,不可被枚举的属性,会被似乎用浅粉色展示;
2)通过方法defineProperty()或defineProperties()所操作的属性(无论是新增或修改),皆被进行了从新定义(是否赋值、是否可配置、是否可枚举等)。
这就是这2个静态方法的作用。