tip:bind方法创造的函数,name属性返回bound加上原函数的名字
Function构造函数创造的函数,name属性返回anonymous
1.属性的可枚举性和遍历
Object.getOwnPropertyDescriptor方法可以获取该属性的描述对象
let obj = {
name:1
}
let desc = Obj.getOwnPropertyDescriptor(obj,name)
/**
{value: 1, writable: true, enumerable: true, configurable: true}
*/
- value 是这个属性的对应的值
- writable 是这个属性是否可写
obj.name = 2;
// obj.name 2
说明这个属性是可写的
- enumerable 这个属性的可枚举性
for...in循环:只遍历对象自身的和继承的可枚举的属性。 // 会返回继承的属性
Object.keys():返回对象自身的所有可枚举的属性的键名。
JSON.stringify():只串行化对象自身的可枚举的属性。
Object.assign(): 忽略enumerable为false的属性,只拷贝对象自身的可枚举的属性。
即是说,如果一个对象的属性的可枚举性是false,则像 Object.keys() 返回的结果中就不会包含这个属性
Object.getOwnPropertyDescriptor(Object.prototype, 'toString').enumerable
// false
Object.getOwnPropertyDescriptor([], 'length').enumerable
// false
对象继承的这些方法由于是不可枚举的,所以我们在对一个对象进行for…in 操作的时候,是不会枚举到这些方法的
ES6 规定,所有 Class 的原型的方法都是不可枚举的
注:尽量不要用for…in循环,而用Object.keys()代替
属性的遍历方法说明:
1.for…in
循环遍历对象自身的和继承的可枚举属性(不含 Symbol 属性)
let obj = {
1:233,
like:1,
[Symbol(1)]:1,
[Symbol(2)]:1,
[Symbol(3)]:1,
[Symbol(4)]:1,
[Symbol(5)]:1,
}
for(let key in obj){
}
// key: 1
// key:like
2.Object.keys(obj)
let obj = {
1:233,
like:1,
[Symbol(1)]:1,
[Symbol(2)]:1,
[Symbol(3)]:1,
[Symbol(4)]:1,
[Symbol(5)]:1,
}
let keyArr = Object.keys(obj);
// ["1","like"]
3.Object.getOwnPropertyNames(obj)
let obj = {
1:233,
like:1,
[Symbol(1)]:1,
[Symbol(2)]:1,
[Symbol(3)]:1,
[Symbol(4)]:1,
[Symbol(5)]:1,
}
let res = Object.getOwnPropertyNames(obj);
// ["1", "like"]
这个方法 与上面的 Object.getOwnPropertyNames(obj) 用法基本相同,不过Object.getOwnPropertyNames(obj) 可以返回对象的不可枚举的属性(不含Symbol 属性)
4.Object.getOwnPropertySymbols(obj) – 返回对象自身的所有 Symbol 属性的键名
let obj = {
1:233,
like:1,
[Symbol(1)]:1,
[Symbol(2)]:1,
[Symbol(3)]:1,
[Symbol(4)]:1,
[Symbol(5)]:1,
}
let res = Object.getOwnPropertySymbols(obj);
/**
[Symbol(1), Symbol(2), Symbol(3), Symbol(4), Symbol(5)]
*/
5.Reflect.ownKeys(obj) --包含对象自身的所有键名
let obj = {
1:233,
like:1,
[Symbol(1)]:1,
[Symbol(2)]:1,
[Symbol(3)]:1,
[Symbol(4)]:1,
[Symbol(5)]:1,
}
let res = Reflect.ownKeys(obj);
// ["1", "like", Symbol(1), Symbol(2), Symbol(3), Symbol(4), Symbol(5)]
以上几种方法共同的属性遍历规则:
```markup6
1.首先遍历所有数值键,按照数值升序排列。
2.其次遍历所有字符串键,按照加入时间升序排列。
3.最后遍历所有 Symbol 键,按照加入时间升序排列。
- enumerable 属性的可配置性
let obj = {
name:1,
code:2
}
看下这个name属性的可配置性:
Object.getOwnPropertyDescriptor(obj,'like')
/*
{value: 1, writable: true, enumerable: true, configurable: true}
*/
冻结对象:
Object.freeze(obj);
Object.getOwnPropertyDescriptor(obj,'name')
// {value: 1, writable: false, enumerable: true, configurable: false}
冻结之后,这个对象的可写和可配置都变为false了,如果这个对象有多层,则内层对象还是可写的
let obj = {
obj1:{
name:1
},
name:1
}
Object.freeze(obj);
Object.getOwnPropertyDescriptor(obj,'name');
obj.obj1.name = 2;
/**
let obj = {
obj1:{
name:2
},
name:1
}
*/
所以如果想通过冻结对象来使得对象不可写的话,需要递归冻结每一层的子对象
- Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
let obj= {
name:1
}
开始配置:
Object.defineProperty(obj,'name',{
writable:true,
enumerable:true,
configurable:false,
value:4
})
console.log(obj);// {name:4}
Object.getOwnPropertyDescriptor(obj,'name')
//{value: 4, writable: true, enumerable: true, configurable: false}
现在我们还是不明白这个 configurable 的用处到底是什么
表示能否通过delete删除属性从而重新定义属性
我们已经将上面这个对象的 name 属性 的configurable 修改为false了,当我们尝试删除这个属性的时候:
delete obj['name']
console.log(obj);// {name:4}