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

查看所有标签

猜你喜欢:

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

区块链技术驱动金融

区块链技术驱动金融

阿尔文德·纳拉亚南、约什·贝努、爱德华·费尔顿、安德鲁·米勒、史蒂文·戈德费德 / 林华、王勇 / 中信出版社,中信出版集团 / 2016-8-25 / CNY 79.00

从数字货币及智能合约技术层面,解读了区块链技术在金融领域的运用。“如果你正在寻找一本在技术层面解释比特币是如何运作的,并且你有一定计算机科学和编程的基本知识,这本书应该很适合你。” 《区块链:技术驱动金融》回答了一系列关于比特币如何运用区块链技术运作的问题,并且着重讲述了各种技术功能,以及未来会形成的网络。比特币是如何运作的?它因何而与众不同?你的比特币安全吗?比特币用户如何匿名?区块链如何......一起来看看 《区块链技术驱动金融》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

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

Base64 编码/解码

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具