2021.04.27(方法的 name 属性、属性的可枚举性和遍历)

方法的 name 属性

函数的 name  属性,返回函数名。对象方法也是函数,因此也有 name  属性。

1.  const person = {
2.  sayName() {
3.  console.log('hello!');
4.  },
5.  };
6.
7.  person.sayName.name // "sayName"

上面代码中,方法的 name  属性返回函数名(即方法名)。

如果对象的方法使用了取值函数( getter  )和存值函数( setter  ),则 name  属性不是在该
方法上面,而是该方法的属性的描述对象的 get  和 set  属性上面,返回值是方法名前加
上 get  和 set  。

1.  const obj = {
2.  get foo() {},
3.  set foo(x) {}
4.  };
5.
6.  obj.foo.name
7.  // TypeError: Cannot read property 'name' of undefined
8.
9.  const descriptor = Object.getOwnPropertyDescriptor(obj, 'foo');
10.
11.  descriptor.get.name // "get foo"
12.  descriptor.set.name // "set foo"

有两种特殊情况: bind  方法创造的函数, name  属性返回 bound  加上原函数的名
字; Function  构造函数创造的函数, name  属性返回 anonymous  。

1.  (new Function()).name // "anonymous"
2.
3.  var doSomething = function() {
4.  // ...
5.  };
6.  doSomething.bind().name // "bound doSomething"

如果对象的方法是一个 Symbol 值,那么 name  属性返回的是这个 Symbol 值的描述。

1.  const key1 = Symbol('description');
2.  const key2 = Symbol();
3.  let obj = {
4.  [key1]() {},
5.  [key2]() {},
6.  };
7.  obj[key1].name // "[description]"
8.  obj[key2].name // ""

上面代码中, key1  对应的 Symbol 值有描述, key2  没有。

属性的可枚举性和遍历

可枚举性

对象的每个属性都有一个描述对象(Descriptor),用来控制该属性的行
为。 Object.getOwnPropertyDescriptor  方法可以获取该属性的描述对象。

1.  let obj = { foo: 123 };
2.  Object.getOwnPropertyDescriptor(obj, 'foo')
3.  // {
4.  // value: 123,
5.  // writable: true,
6.  // enumerable: true,
7.  // configurable: true
8.  // }

描述对象的 enumerable  属性,称为“可枚举性”,如果该属性为 false  ,就表示某些操作会忽略
当前属性。

目前,有四个操作会忽略 enumerable  为 false  的属性。

for...in  循环:只遍历对象自身的和继承的可枚举的属性。
Object.keys()  :返回对象自身的所有可枚举的属性的键名。
JSON.stringify()  :只串行化对象自身的可枚举的属性。
Object.assign()  : 忽略 enumerable  为 false  的属性,只拷贝对象自身的可枚举的属性。

1.  Object.getOwnPropertyDescriptor(Object.prototype, 'toString').enumerable
2.  // false
3.
4.  Object.getOwnPropertyDescriptor([], 'length').enumerable
5.  // false

上面代码中, toString  和 length  属性的 enumerable  都是 false  ,因此 for...in  不会
遍历到这两个继承自原型的属性。

另外,ES6 规定,所有 Class 的原型的方法都是不可枚举的。

1.  Object.getOwnPropertyDescriptor(class {foo() {}}.prototype, 'foo').enumerable
2.  // false

总的来说,操作中引入继承的属性会让问题复杂化,大多数时候,我们只关心对象自身的属性。所以,
尽量不要用 for...in  循环,而用 Object.keys()  代替。

属性的遍历

ES6 一共有 5 种方法可以遍历对象的属性。
(1)for…in
for...in  循环遍历对象自身的和继承的可枚举属性(不含 Symbol 属性)。
(2)Object.keys(obj)
Object.keys  返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含 Symbol 属
性)的键名。
(3)Object.getOwnPropertyNames(obj)
Object.getOwnPropertyNames  返回一个数组,包含对象自身的所有属性(不含 Symbol 属性,但
是包括不可枚举属性)的键名。
(4)Object.getOwnPropertySymbols(obj)
Object.getOwnPropertySymbols  返回一个数组,包含对象自身的所有 Symbol 属性的键名。
(5)Reflect.ownKeys(obj)
Reflect.ownKeys  返回一个数组,包含对象自身的(不含继承的)所有键名,不管键名是 Symbol
或字符串,也不管是否可枚举。
以上的 5 种方法遍历对象的键名,都遵守同样的属性遍历的次序规则。
首先遍历所有数值键,按照数值升序排列。
其次遍历所有字符串键,按照加入时间升序排列。
最后遍历所有 Symbol 键,按照加入时间升序排列。

1.  Reflect.ownKeys({ [Symbol()]:0, b:0, 10:0, 2:0, a:0 })
2.  // ['2', '10', 'b', 'a', Symbol()]

上面代码中, Reflect.ownKeys  方法返回一个数组,包含了参数对象的所有属性。这个数组的属性次序是这样的,首先是数值属性 2  和 10  ,其次是字符串属性 b  和 a  ,最后是 Symbol 属
性。

 

2021-04-27  15:13:35

 

posted @ 2021-04-27 15:14  铁打的代码流水的bug  阅读(107)  评论(0)    收藏  举报