ES6 之 對象屬性的可枚舉性和遍歷


1.Object.getOwnPropertyDescriptor()

解釋:獲取對對象屬性的描述對象。

let obj = { foo: 123 };
console.log(Object.getOwnPropertyDescriptor(obj, 'foo'))

顯示結果:

{
    configurable: true
    enumerable: true
    value: 123
    writable: true
    __proto__: Object
}

enumerable屬性,稱為可枚舉性,如果為 false 時,就表示某些操作會忽略當前屬性。

目前,有四個操作會忽略enumerable為 false 的屬性。

  • for...in循環:只遍歷對象自身的和繼承的可枚舉的屬性。
  • Object.keys():返回對象自身的所有可枚舉的屬性的鍵名。使用這個遍歷對象!
  • JSON.stringify():只串行化對象自身的可枚舉的屬性。
  • Object.assign(): 忽略enumerable為false的屬性,只拷貝對象自身的可枚舉的屬性
Object.getOwnPropertyDescriptor(Object.prototype, 'toString').enumerable // false 
 
Object.getOwnPropertyDescriptor([], 'length').enumerable // false

// toString和length屬性的enumerable都是false,因此for...in不會遍歷到這兩個繼承自原型的屬性。

2. Object.getOwnPropertyDescriptors()

Object.getOwnPropertyDescriptors 方法,返回指定對象所有自身屬性(非繼承屬性)的描述對象。

const obj = {   foo: 123,   get bar() { return 'abc' } }; 
 
Object.getOwnPropertyDescriptors(obj) 

// { foo: 
//    { value: 123, 
//      writable: true, 
//      enumerable: true, 
//      configurable: true }, 
//   bar: 
//    { get: [Function: bar],
//      set: undefined, 
//      enumerable: true, 
//      configurable: true } }

上面代碼中,Object.getOwnPropertyDescriptors(obj)方法返回一個對象,所有原對象的屬性名都是該對象的屬性名,對應的屬性值就是該屬性的描述對象。

 

3. Object.setPrototypeOf()

用於設置一個對象的原型對象。

// 格式 
Object.setPrototypeOf(object, prototype) 
 
// 用法 
const o = Object.setPrototypeOf({}, null); 

// 該方法等同於下面的函數。
function (obj, proto) {   
    obj.__proto__ = proto;   
    return obj; 
}

例子:

let proto = {}; 
let obj = { x: 10 }; 
Object.setPrototypeOf(obj, proto); 
 
proto.y = 20;
proto.z = 40; 
 
obj.x // 10 
obj.y // 20 
obj.z // 40

注意:

  1. 如果第一個參數不是對象,會自動轉為對象。但是由於返回的還是第一個參數,所以這個操作不會產生任何效果。

  2. 由於undefined和null無法轉為對象,所以如果第一個參數是undefined或null,就會報錯。

4. Object.getPrototypeOf()

該方法與Object.setPrototypeOf方法配套,用於讀取一個對象的原型對象。

Object.getPrototypeOf(obj); 
  1. 如果參數不是對象,會被自動轉為對象。

  2. 如果參數是undefined或null,它們無法轉為對象,所以會報錯。

5. super關鍵字

我們知道,this關鍵字總是指向函數所在的當前對象,ES6 又新增了另一個類似的關鍵字super,指向當前對象的原型對象

const proto = {   foo: 'hello' }; 
 
const obj = {   
    find() {     
        return super.foo;   
    } 
}; 

Object.setPrototypeOf(obj, proto);
obj.find() // "hello" 
// 上面代碼中,對象obj的find方法之中,通過super.foo引用了原型對象proto的foo屬性。

注意,super關鍵字表示原型對象時,只能用在對象的方法之中,用在其他地方都會報錯。

JavaScript 引擎內部,super.foo等同於Object.getPrototypeOf(this).foo(屬性)或Object.getPrototypeOf(this).foo.call(this)(方法)。

例題:

const proto = {   
    x: 'hello',   
    foo() {     
        console.log(this.x);   
    }, 
}; 
 
const obj = {   
    x: 'world',   
    foo() {    
        super.foo();   
    } 
} 
 
Object.setPrototypeOf(obj, proto); 
 
obj.foo() // "world" 

// 上面代碼中,super.foo指向原型對象proto的foo方法,但是綁定的this卻還是當前對象obj,因此輸出的就是world。

 

6. Object.keys(),Object.values(),Object.entries()

Object.keys方法,返回一個數組,成員是參數對象自身的(不含繼承的)所有可遍歷(enumerable)屬性的鍵名。

var obj = { foo: 'bar', baz: 42 }; 
Object.keys(obj) // ["foo", "baz"] 

 

ES2017 引入了跟Object.keys配套的Object.valuesObject.entries,作為遍歷一個對象的補充手段,供for...of循環使用

Object.values方法返回一個數組,成員是參數對象自身的(不含繼承的)所有可遍歷(enumerable)屬性的鍵值。

const obj = { 100: 'a', 2: 'b', 7: 'c' }; 
Object.values(obj) // ["b", "c", "a"] 

上面代碼中,屬性名為數值的屬性,是按照數值大小,從小到大遍歷的,因此返回的順序是b、c、a。

Object.values只返回對象自身的可遍歷屬性。

 

Object.entries方法返回一個數組,成員是參數對象自身的(不含繼承的)所有可遍歷(enumerable)屬性的鍵值對數組。

const obj = { foo: 'bar', baz: 42 }; 
Object.entries(obj) // [ ["foo", "bar"], ["baz", 42] ]

除了返回值不一樣,該方法的行為與Object.values基本一致。

 

 遍歷語法的比較

對於數組來說:

for循環:最原始的寫法;

forEach:無法中途跳出forEach循環,break命令或return命令都不能奏效;

for...in...:遍歷可以獲得數組的鍵名,有以下缺點:

  數組的鍵是number,而遍歷出來的鍵是字符串;

  for...in循環不僅遍歷數字鍵名,還會遍歷手動添加其他鍵,甚至包括原型鏈上的鍵

  在某些情況下,for...in循環會以任意順序遍歷鍵名

  總之,for...in循環主要是為了遍歷對象而設計的,不適用於遍歷數組

 for...of:遍歷數組 

  有着同for..in樣簡單語法,但是沒有for...in那些缺點,

  不同於 forEach 方法,它可以與 break 、 continue 和 return 配合使用。

  提供了遍歷所有數據結構的統一操作接口。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM