proto
新创建对象的原型对象。propertiesObject
可选。需要传入一个对象,该对象的属性类型参照Object.defineProperties()的第二个参数。如果该参数被指定且不为 undefined,该传入对象的自有可枚举属性(即其自身定义的属性,而不是其原型链上的枚举属性)将为新创建的对象添加指定的属性值和对应的属性描述符。
let proto = {
name: 'wang',
age: 22
}
let obj = Object.create(proto,{
sex:{
value: 'boy',
writable: true
}
})
console.log(obj.name) // wang
console.log(obj) // { sex: 'boy }
obj
在其上定义或修改属性的对象。prop
要定义或修改的属性的名称或Symbol
。descriptor
要定义或修改的属性描述符。
对象里目前存在的属性描述符有两种主要形式:数据描述符和存取描述符。数据描述符是一个具有值的属性,该值可以是可写的,也可以是不可写的。存取描述符是由 getter 函数和 setter 函数所描述的属性。一个描述符只能是这两者其中之一;不能同时是两者。
这两种描述符都是对象。它们共享以下可选键值(默认值是指在使用 Object.defineProperty()
定义属性时,省略字段的默认值):
-
configurable
当且仅当该属性的configurable
键值为true
时,该属性的描述符才能够被改变,同时该属性也能从对应的对象上被删除。默认为false
。 -
enumerable
当且仅当该属性的enumerable
键值为true
时,该属性才会出现在对象的枚举属性中,在枚举对象属性时会被枚举到(for...in
或Object.keys
方法)。默认为false
。 -
value
该属性对应的值。可以是任何有效的JavaScript
值(数值
,对象
,函数
等)。默认为undefined
。 -
wriatable
当且仅当该属性的writable
键值为true
时,属性的值,也就是上面的value
,才能被赋值运算符改变。默认为false
。 -
set
属性的setter
函数,如果没有setter
,则为undefined
。当属性值被修改时,会调用此函数。该方法接受一个参数(也就是被赋予的新值),会传入赋值时的 this 对象。默认为undefined
。 -
get
属性的getter
函数,如果没有getter
,则为undefined
。当访问该属性时,会调用此函数。执行时不传入任何参数,但是会传入this
对象(由于继承关系,这里的this
并不一定是定义该属性的对象)。该函数的返回值会被用作属性的值。默认为undefined
。
configurable | enumerable | value | writable | get | set | 数据描述符 | 可以 | 可以 | 可以 | 可以 | 不可以 | 不可以 | 存取描述符 | 可以 | 可以 | 不可以 | 不可以 | 可以 | 可以 |
---|
let obj = {}
Object.defineProperty(obj, 'sex', {
value: 'boy',
writable: true,
enumerable: false,
configurable: true, // configurable:true 时可以重新定义属性描述符
})
Object.defineProperty(obj, 'age', {
value: 22,
writable: false,
enumerable: true,
configurable: false // configurable:false 时不能重新定义属性描述符
})
console.log(Object.entries(obj)) // [["age", 22]]
// Object.defineProperty(obj, 'age', {
// value: 44,
// writable: true,
// enumerable: false,
// configurable: true
// })
// 报错 Uncaught TypeError: Cannot redefine property: age 因为第一次定义 'age' 时 configurable:false 所以不能重新定义
Object.defineProperty(obj, 'sex', {
value: 'boy',
writable: false,
enumerable: true,
configurable: true,
})
console.log(Object.entries(obj)) // [ ["sex", "boy"], ["age", 22]]
obj
在其上定义或修改属性的对象。props
要定义其可枚举属性或修改的属性描述符的对象。对象中存在的属性描述符主要有两种:数据描述符和访问器描述符(更多详情,请参阅Object.defineProperty())。
let obj = { sex: 'girl' }
Object.defineProperties(obj, {
sex: {
writable: false // false 时赋值语句改变不了sex的值
},
age: {
value: 100,
writable: true
}
})
obj.sex = 'boy'; // 不能改变值
obj.age = 22; // 可以改变值
console.log(obj) // { sex: 'girl', age: 22 }
Object.defineProperties(obj, {
sex: {
value: 'boy' // 可以改变值
},
})
console.log(obj) // { sex: 'boy' }
function Archiver() {
let temperature = null;
let archive = [];
Object.defineProperty(this, 'temperature', {
get: function() {
console.log('get!');
return temperature;
},
set: function(value) {
temperature = value;
archive.push({ val: temperature });
}
});
this.getArchive = function() { return archive; };
}
let arc = new Archiver();
arc.temperature; // 'get!'
arc.temperature = 11;
arc.temperature = 13;
arc.getArchive(); // [{ val: 11 }, { val: 13 }]
const obj = {
foo: 123,
get bar() { return 'abc' }
};
Object.getOwnPropertyDescriptors(obj)
// { foo:
// { value: 123,
// writable: true,
// enumerable: true,
// configurable: true },
// bar:
// { get: [Function: get bar],
// set: undefined,
// enumerable: true,
// configurable: true } }
该方法的引入目的,主要是为了解决Object.assign()
无法正确拷贝get
属性和set
属性的问题。
const people = {
set name(value) {
console.log(value);
}
};
const target = {};
Object.assign(target, people);
Object.getOwnPropertyDescriptor(target, 'name')
// { value: undefined, 这是因为Object.assign方法总是拷贝一个属性的值,而不会拷贝它背后的赋值方法或取值方法。
// writable: true,
// enumerable: true,
// configurable: true }
Object.getOwnPropertyDescriptors()
方法配合Object.defineProperties()
方法,就可以实现正确拷贝。
const source = {
set name(value) {
console.log(value);
}
};
const target = {};
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
Object.getOwnPropertyDescriptor(target, 'name')
// { get: undefined,
// set: [Function: set name],
// enumerable: true,
// configurable: true }
不同之处只有两个:一是+0
不等于 -0
,二是 NaN
等于自身。
const target = { a: 1 };
const source1 = { b: 2 };
const source2 = { c: 3, b: 'source2' };
Object.assign(target, source1, source2);
target // { a: 1, b: 'source2', c: 3 }
该方法的一个用处是配合URLSearchParams
对象,将查询字符串转为对象。
Object.fromEntries(new URLSearchParams('foo=bar&baz=qux'))
// { foo: "bar", baz: "qux" }
let name = Symbol.for('name');
let obj = {
[name]: 'name',
}
Object.defineProperties(obj, {
age: {
value: 22,
enumerable: false,
writable: true
},
sex: {
value: 'boy',
enumerable: false,
writable: true
}
})
console.log(Object.getOwnPropertyNames(obj)); // ["age", "sex"]
console.log(Object.getOwnPropertySymbols(obj)); // [Symbol(name)]
默认情况下,对象都是可以扩展的,即对象可以添加新的属性和方法。使用Object.preventExtensions()、Object.seal()和Object.freeze()方法都可以标记对象为不可扩展。
在ES5中,如果参数是非对象类型,会抛出TypeError异常。
在ES6中,如果参数是非对象类型,则会认为是一个不可扩展的普通对象,因此会返回false。
对象默认是可扩展的,即可以添加新的属性。如果一个对象被配置为不可扩展,则无法添加新的属性,这是一个不可逆的操作。不可扩展的对象仍然可以删除已有的属性(取决于属性的可配置性),但如果尝试添加新的属性到不可扩展对象,会引发TypeError异常(严格模式)或静默失败。
Object.preventExtensions()仅阻止添加自身的属性。但属性仍然可以添加到对象原型,而这个不可扩展的对象同样会继承这些后来添加的原型对象的属性。
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!