ECMAScript 之 for...in 與 class 研究

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

内容简介:若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 研究》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

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

Dive Into Python 3

Dive Into Python 3

Mark Pilgrim / Apress / 2009-11-6 / USD 44.99

Mark Pilgrim's Dive Into Python 3 is a hands-on guide to Python 3 (the latest version of the Python language) and its differences from Python 2. As in the original book, Dive Into Python, each chapter......一起来看看 《Dive Into Python 3》 这本书的介绍吧!

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具