第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

全部開發(fā)者教程

ES6-10 入門教程

ES6+ Object.keys()

1. 前言

我們知道迭代對象可以使用 for...in 循環(huán)來做,但 for...in 循環(huán)會枚舉其原型鏈上的屬性,這使得我們在遍歷時需要判斷是不是原型鏈屬性。Object.keys() 可以接受一個對象返回一個可枚舉的數(shù)組,數(shù)組中的元素的排列順序和使用 for...in 循環(huán)遍歷返回的順序是一致的。
Object.keys() 在 ES5 中就有此方法,但是在設(shè)計上存在一定的缺陷,ES6 對其底層做了重大的更新。比如:在 ES5 中,如果此方法的參數(shù)不是對象(而是一個原始值),那么它會拋出 TypeError。在 ES2015 中,非對象的參數(shù)將被強(qiáng)制轉(zhuǎn)換為一個對象。

// ES5 代碼
Object.keys("imooc");  // TypeError: "imooc" is not an object
// ES6 代碼
Object.keys("imooc");  // ["0", "1", "2", "3", "4"]

現(xiàn)在的瀏覽器已經(jīng)基本都支持 ES6 的結(jié)果了,下面我們來系統(tǒng)性地認(rèn)識一下 Object.keys()

2. 方法詳情

2.1 基本語法

Object.keys() 方法會返回一個由一個給定對象的自身可枚舉屬性組成的數(shù)組,數(shù)組中屬性名的排列順序和正常循環(huán)遍歷該對象時返回的順序一致 。

語法使用:

Object.keys(obj)

參數(shù)解釋:

參數(shù) 描述
obj 要返回其枚舉自身屬性的對象。

2.2 基本實(shí)例

用于對象時返回對象鍵值作為數(shù)組:

var obj =  {
	name:  'imooc',
	type:  'ES6 Wiki'
}
console.log(Object.keys(obj));
// ["name", "type"]

用于數(shù)組類型:

var arr = ['a',  'b',  'c'];
console.log(Object.keys(arr));
// console: ['0', '1', '2']

也可以用于類數(shù)組中:

var obj =  {  0:  'a',  1:  'b',  2:  'c'  };
console.log(Object.keys(obj));  // ['0', '1', '2']

鍵值是數(shù)字和字符串混合時,會先進(jìn)行數(shù)值的排序,然后再按添加的順序排列字符串:

var obj =  {  name:  'imooc',  10:  'a',  3:  'b',  age:  7  };
console.log(Object.keys(obj));
// ["3", "10", "name", "age"]

Object.keys() 不能獲取不可枚舉屬性:

// 創(chuàng)建一個obj對象帶有一個不可枚舉屬性
var obj =  Object.create({},  {
	getFoo:  {
		value:  function  ()  {  return  this.foo;  }
	}
});
obj.foo =  1;
console.log(Object.keys(obj));  // ['foo']

3. 自動排序問題

在說自動排序問題前,我們先來看下三個例子:

var obj1 =  {99:  '九十九',  5:  '五',  7:  '七'}
Object.keys(obj1) // ["5", "7", "99"]

var obj2 =  {c:  'z',  a:  'x',  b:  'y'}
Object.keys(obj2) // ["c", "a", "b"]

var obj3 =  {  name:  'imooc',  10:  'a',  3:  'b',  age:  7  };
Object.keys(obj3);  // ["3", "10", "name", "age"]

上面的例子可以看出當(dāng)鍵值是數(shù)字時返回的值會自動排序,即使在混合情況下也會先進(jìn)行排序后把數(shù)字項(xiàng)放在數(shù)組中前面,而鍵值對是字符串時則不會被排序。那當(dāng) Object.keys() 被調(diào)用時內(nèi)部都發(fā)生了什么呢?

通過查閱 ECMA262 規(guī)范知道,Object.keys 在內(nèi)部會根據(jù)對象的屬性名 key 的類型進(jìn)行不同的排序邏輯。分三種情況:

  1. 如果屬性名的類型是 Number,那么 Object.keys 返回值是按照 key 從小到大排序;
  2. 如果屬性名的類型是 String,那么 Object.keys 返回值是按照屬性被創(chuàng)建的時間升序排序;
  3. 如果屬性名的類型是 Symbol,那么邏輯同 String 相同。

那內(nèi)部到底發(fā)生了什么呢?

3.1 將參數(shù)轉(zhuǎn)換為對象

Object.keys() 調(diào)用時會根據(jù)傳入的參數(shù)進(jìn)行類型轉(zhuǎn)換,轉(zhuǎn)換為 Object 類型的值:

參數(shù)類型 結(jié)果
Undefined 拋出 TypeError
Null 拋出 TypeError
Boolean 返回一個新的 Boolean 對象
Number 返回一個新的 Number 對象
String 返回一個新的 String 對象
Symbol 返回一個新的 Symbol 對象
Object 直接將 Object 返回

實(shí)例:

// 參數(shù)是undefined或null
Object.keys(undefined) // Uncaught TypeError: Cannot convert undefined or null to object
// 參數(shù)是數(shù)值
Object.keys(123) // []
// 參數(shù)是字符串
Object.keys('imooc') // ["0", "1", "2", "3", "4"]

上面的代碼中,參數(shù)是數(shù)值時為什么會返回空數(shù)組呢?是因?yàn)閿?shù)值轉(zhuǎn)換為對象時沒有可提取的屬性,而字符串在 ES5 時會報錯,ES6 進(jìn)行了修復(fù),因?yàn)?String 對象有可提取的屬性??聪旅鎯蓮垐D:

圖片描述

圖片描述

3.2 獲取屬性列表

上面我們說到了 Object.keys() 會對參數(shù)做類型轉(zhuǎn)換,在獲取屬性的時候會調(diào)用內(nèi)部方法 EnumerableOwnProperties ( O, kind ) 來計算對象上所有可枚舉的屬性 ownKeys,這里的 ownKeys 類型時 list 類型,只用于內(nèi)部實(shí)現(xiàn)。

然后聲明變量用于存放遍歷對象后得到的屬性集合 properties,properties 也是 List 類型,循環(huán)對象的 ownKeys 將每個元素添加到 properties 列表中。最后返回 properties。

為什么會對數(shù)值進(jìn)行排序,是因?yàn)樵谡{(diào)用 EnumerableOwnProperties(O, kind) 方法執(zhí)行時,又會調(diào)用 OrdinaryOwnPropertyKeys(O) ,對于不同類型的屬性,會按不同的順序放入 properties 屬性列表中:

  1. 先處理類型為數(shù)值的屬性,從小到大放到屬性列表中;
  2. 再處理類型為字符串的屬性,按該屬性的創(chuàng)建順序,放到屬性列表中;
  3. 最后處理類型為 Symbol 的屬性,按創(chuàng)建順序,放到屬性列表中。

這樣就知道為什么會對數(shù)值進(jìn)行排序了,是 ECMA262 中 OrdinaryOwnPropertyKeys(o) 規(guī)定的。其原因是 OrdinaryOwnPropertyKeys(o) 內(nèi)部方法不只是給 Object.keys() 使用的,是通用的規(guī)則。
最后將 properties 列表轉(zhuǎn)化為數(shù)組就得到了 Object.keys() 的結(jié)果。

4. 小結(jié)

本節(jié)主要學(xué)習(xí)了 Object.keys() 方法用于獲取對象上可枚舉屬性,并返回屬性的數(shù)組,數(shù)組中的元素的排列順序和使用 for...in 循環(huán)遍歷返回的順序是一致的。這里需要注意的是,如果對象上的屬性是數(shù)值時,會被排序。