ECMAScript 之 for...in 與 class 研究

栏目: JavaScript · 发布时间: 6年前

内容简介:若ECMAScript 2015

Object.keys()for...in 的差異在於 Object.keys() 只能顯示目前 Object 的 Property Key,而 for...in 會連同 Prototype 的 Property Key 一併顯示。

for...in 搭配 Constructor Function 或 Object.create() 時一切正常,但搭配 class 時,就無法顯示 Prototype 的 Property Key 了,為什麼會這樣呢 ?

Version

ECMAScript 2015

Constructor Function

function Person(firstName, lastName) {
  this.firstName = firstName;
  this.lastName = lastName;
}

Person.prototype.fullName = function() {
  return this.firstName + ' ' + this.lastName;
};
 
const person = new Person('Sam', 'Xiao');

for(let key in person)
  console.log(key);

// firstName
// lastName
// fullName

由 Constructor Function 建立 object,並將 method 定義在 Prototype,這是 ECMAScript OOP 標準寫法。

當對 object 使用 for...in ,會顯示所有的 Property Key,連 Prototype 也會顯示。

ECMAScript 之 for...in 與 class 研究

fullName()
for...in
fullName

Object.create

const prototype = {
  fullName: function() {
    return this.firstName + ' ' + this.lastName;
  },
};

const person = Object.create(prototype);
person.firstName = 'Sam';
person.lastName = 'Xiao';

for(let key in person)
  console.log(key);

// firstName
// lastName
// fullName

Prototype 除了事後在 Constructor Function 動態指定外,也可以事先建立 Prototype object,然後傳入 Object.create()

一樣使用 for...in ,也如預期列出 Prototype 的 Property Key。

ECMAScript 之 for...in 與 class 研究

Object.create()
for...in
fullName

Class

class Person {
  constructor(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
  }

  fullName() {
    return this.firstName + ' ' + this.lastName;
  }
}

const person = new Person('Sam', 'Xiao');

for(let key in person)
  console.log(key);

// firstName
// lastName

ECMAScript 2015 導入 class 語法後,method 可以直接定義在 class 內,會自己幫我們定義在 Prototype。

但使用 for..in ,卻發現 Prototype 的 fullName 無法顯示,退化成與 Object.keys() 功能一樣,為什麼會這樣呢 ?

ECMAScript 之 for...in 與 class 研究

for...in
fullName

Why ?

for...inObject.keys() 都僅能列出 Enumerable Property,所以很有可能 class 的寫法,造成 Prototype 的 property 為 Non Enumerable Property,造成 for...in 無法顯示。

class Person {
  constructor(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
  }

  fullName() {
    return this.firstName + ' ' + this.lastName;
  }
}

const person = new Person('Sam', 'Xiao');
console.log(Object.getOwnPropertyDescriptor(person, 'firstName'));
console.log(Object.getOwnPropertyDescriptor(person, 'lastName'));
console.log(Object.getOwnPropertyDescriptor(person.__proto__, 'fullName'));

for(let key in person)
  console.log(key);

Object.getOwnPropertyDescriptor() 會傳回每個 property 的屬性,藉此觀察是否為 Non Enumerable。

ECMAScript 之 for...in 與 class 研究

  1. 特別加上 Object.getOwnPropertyDescriptor() 觀察之
  2. 果然如假設所言,Prototype 的 fullNameenumerablefalse ,因此 for...in 無法顯示
'use strict';

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

var Person = function () {
  function Person(firstName, lastName) {
    _classCallCheck(this, Person);

    this.firstName = firstName;
    this.lastName = lastName;
  }

  _createClass(Person, [{
    key: 'fullName',
    value: function fullName() {
      return this.firstName + ' ' + this.lastName;
    }
  }]);

  return Person;
}();

var person = new Person('Sam', 'Xiao');

for (var key in person) {
  console.log(key);
}
//# sourceMappingURL=es6class.js.map

從另外一個角度,我們由 Babel 所 transpile 的 ES5 觀察。

descriptor.enumerable = descriptor.enumerable || false;

對於 Prototype 的 property,Babel 也是將 enumerable 設定為 false

由這兩點都可以證明,當使用 class 寫法時,根據 ECMAScript 2015 規格,都會將 Prototype 的 property 設定為 Non Enumerable Property,也就是 for...in 功能將等同 Object.keys()

Conclusion

  • for...in 為 ECMAScript 3 所定義,而 Object.keys() 為 ECMAScript 5.1 所加入,理論上兩者的差異就在於 Prototype 部分,但 ECMAScript 2015 支援 class 後,又使得 for..inObject.keys() 功能趨於一至,個人是不太喜歡這種改變,這使得 for...in 與過去的觀念不同,算 breaking change,但既然 ECMAScript 2015 規格就是這樣定義,也只能自己注意這個微小的差異了

以上所述就是小编给大家介绍的《ECMAScript 之 for...in 與 class 研究》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Netty实战

Netty实战

诺曼·毛瑞尔(Norman Maurer)、马文·艾伦·沃尔夫泰尔(Marvin Allen Wolfthal) / 何品 / 人民邮电出版社 / 2017-5-1 / 69.00

编辑推荐 - Netty之父”Trustin Lee作序推荐 - 阿里巴巴中间件高级技术专家为本书中文版作序推荐 - 系统而详细地介绍了Netty的各个方面并附带了即用型的优质示例 - 附带行业一线公司的案例研究 - 极实用的Netty技术书 无论是构建高性能的Web、游戏服务器、推送系统、RPC框架、消息中间件还是分布式大数据处理引擎,都离不开Nett......一起来看看 《Netty实战》 这本书的介绍吧!

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

URL 编码/解码
URL 编码/解码

URL 编码/解码

html转js在线工具
html转js在线工具

html转js在线工具