欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Object.keys?詭異特性示例詳解

 更新時(shí)間:2022年10月13日 08:35:40   作者:南玖  
這篇文章主要介紹了Object.keys?詭異特性示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

先從‘詭異’的問(wèn)題入手

  • 例1: 純Number類型的屬性
const obj = {
  1: 1,
  6: 6,
  3: 3,
  2: 2
}
console.log('keys', Object.keys(obj)) 
// ['1', '2', '3', '6']

返回的key為什么自動(dòng)按照升序排序了?

  • 例2: 純String類型的屬性
const obj2 = {
  a: 'a',
  c: 'c',
  f: 'f',
  b: 'b',
}
console.log(Object.keys(obj2))
// ['a', 'c', 'f', 'b']

這里為什么又不自動(dòng)排序了?

看到這里是不是覺(jué)得很懵?話不多說(shuō),我們先查文檔,看看mdn上對(duì)Object.keys的描述:

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

emm,然而它并沒(méi)有說(shuō)到底是按哪種順序返回的。

探索

既然文檔上找不到,那我們就一步一步來(lái)慢慢研究

Object.keys的polyfill的實(shí)現(xiàn)

if (!Object.keys) {
  Object.keys = (function () {
    var hasOwnProperty = Object.prototype.hasOwnProperty,
        hasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'),
        dontEnums = [
          'toString',
          'toLocaleString',
          'valueOf',
          'hasOwnProperty',
          'isPrototypeOf',
          'propertyIsEnumerable',
          'constructor'
        ],
        dontEnumsLength = dontEnums.length;
    return function (obj) {
      if (typeof obj !== 'object' && typeof obj !== 'function' || obj === null) throw new TypeError('Object.keys called on non-object');
      var result = [];
      for (var prop in obj) {
        if (hasOwnProperty.call(obj, prop)) result.push(prop);
      }
      if (hasDontEnumBug) {
        for (var i=0; i < dontEnumsLength; i++) {
          if (hasOwnProperty.call(obj, dontEnums[i])) result.push(dontEnums[i]);
        }
      }
      return result;
    }
  })()
};

Object.keys的polyfill的實(shí)現(xiàn),我們可以發(fā)現(xiàn)它內(nèi)部其實(shí)是用for...in來(lái)實(shí)現(xiàn)的。那我們就可以去查找for...in遍歷時(shí)的順序規(guī)則。然而它也并沒(méi)有介紹遍歷的順序是怎樣的,那么我們就只能去查找ECMAScript的規(guī)范了。

Object.keys的規(guī)范定義

調(diào)用ToObject(O)將結(jié)果賦值給變量obj

調(diào)用EnumerableOwnPropertyNames(obj, "key")將結(jié)果賦值給變量nameList

調(diào)用CreateArrayFromList(nameList)得到最終的結(jié)果

第一步:將參數(shù)轉(zhuǎn)換成Object(ToObject(O))

因?yàn)镺bject.keys內(nèi)部會(huì)調(diào)用ToObject(O)方法,所以它不只是可以接受對(duì)象參數(shù),還可以接受其它類型的參數(shù),下面這張表就是ToObject根據(jù)不同類型的值轉(zhuǎn)成Object的映射:

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

我們通常給Object.keys傳的參數(shù)都會(huì)是一個(gè)對(duì)象,但我們也可以來(lái)看看其它類型值的返回值會(huì)是怎樣的?

  • Number
console.log(Object.keys(123)) // []

返回的是空數(shù)組,這是因?yàn)閚ew Number(123)并沒(méi)有可提取的屬性

  • String
console.log(Object.keys('123')) // [ '0', '1', '2' ]

字符串之所以返回的不是空數(shù)組,是因?yàn)閚ew String('123')有可以提取的屬性

第二步:通過(guò)轉(zhuǎn)換后的對(duì)象獲得屬性列表properties。

(順序取決于這里)

對(duì)象屬性列表是通過(guò) EnumerableOwnPropertyNames 獲取的,其中比較重要的是調(diào)用對(duì)象的內(nèi)部方法OwnPropertyKeys獲得對(duì)象的ownKeys(這些內(nèi)容可以在ECMAScript規(guī)范里面找到,就不展開介紹了,我們重點(diǎn)看排序)

The [[OwnPropertyKeys]] internal method of an ordinary object O takes no arguments. It performs the following steps when called:

Return ! OrdinaryOwnPropertyKeys(O).

通過(guò)上面的介紹,我們可以發(fā)現(xiàn)keys的排序取決于 OrdinaryOwnPropertyKeys(O)

翻譯過(guò)來(lái)就是:

  • 創(chuàng)建一個(gè)空的列表用于存放 keys
  • 將所有合法的數(shù)組索引按升序的順序存入
  • 將所有字符串類型索引按屬性創(chuàng)建時(shí)間以升序的順序存入
  • 將所有 Symbol 類型索引按屬性創(chuàng)建時(shí)間以升序的順序存入
  • 返回 keys

注意:屬性列表properties為L(zhǎng)ist類型(List類型ECMAScript規(guī)范類型

第三步:將List類型的屬性列表properties轉(zhuǎn)換為Array得到最終的結(jié)果。

將List類型的屬性列表轉(zhuǎn)換成Array類型非常簡(jiǎn)單:

  • 先聲明一個(gè)變量array,值是一個(gè)空數(shù)組
  • 循環(huán)屬性列表,將每個(gè)元素添加到array
  • array返回

總結(jié)

Object.keys返回的對(duì)象屬性順序

  • 將所有合法的數(shù)組索引按升序排序
  • 將所有字符串類型索引按屬性創(chuàng)建時(shí)間以升序排序
  • 將所有 Symbol 類型索引按屬性創(chuàng)建時(shí)間以升序排序

合法數(shù)組索引指的是正整數(shù),負(fù)數(shù)或者浮點(diǎn)數(shù)一律當(dāng)做字符串處理。嚴(yán)格來(lái)說(shuō)對(duì)象屬性沒(méi)有數(shù)字類型的,無(wú)論是數(shù)字還是字符串,都會(huì)被當(dāng)做字符串來(lái)處理。

看題

const obj = {}
obj[-1] = -1
obj[1] = 1
obj[1.1] = 1.1
obj['2'] = '2'
obj['c'] = 'c'
obj['b'] = 'b'
obj['a'] = 'a'
obj[2] = 2
obj[Symbol(1)] = Symbol(1)
obj[Symbol('a')] = Symbol('a')
obj[Symbol('b')] = Symbol('b')
obj['d'] = 'd'
console.log(Object.keys(obj))

經(jīng)過(guò)上面對(duì)Object.key特性的介紹,想必大家都不會(huì)再搞錯(cuò)Object.keys的輸出順序了吧。

答案:

[ '1', '2', '-1', '1.1', 'c', 'b', 'a', 'd' ]

看到答案很多同學(xué)是不是有很多疑問(wèn)?

如何理解對(duì)象屬性是正整數(shù)還是字符串?

首先我們上面說(shuō)過(guò)合法數(shù)組索引指的是正整數(shù),負(fù)數(shù)或者浮點(diǎn)數(shù)一律當(dāng)做字符串處理。嚴(yán)格來(lái)說(shuō)對(duì)象屬性沒(méi)有數(shù)字類型的,無(wú)論是數(shù)字還是字符串,都會(huì)被當(dāng)做字符串來(lái)處理。

所以上面只有1,'2',2是合法數(shù)組索引,但我們知道其實(shí)它們都會(huì)被轉(zhuǎn)成字符串,所以后面的2會(huì)將前面的'2'覆蓋,然后它們按升序排序。然后負(fù)數(shù)與浮點(diǎn)數(shù)一律當(dāng)做字符串處理按屬性創(chuàng)建時(shí)間以升序排序。這樣就可以得到上面的答案了。

為什么沒(méi)有Symbol類型?

因?yàn)樵?EnumerableOwnPropertyNames 的規(guī)范中規(guī)定了返回值只應(yīng)包含字符串屬性(上面說(shuō)了數(shù)字其實(shí)也是字符串)。

我們也可以在MDN上查看關(guān)于 Object.getOwnPropertyNames() 的描述。

Object.getOwnPropertyNames() 方法返回一個(gè)由指定對(duì)象的所有自身屬性的屬性名(包括不可枚舉屬性但不包括 Symbol 值作為名稱的屬性)組成的數(shù)組。

所以 Symbol 屬性是不會(huì)被返回的,如果要返回 Symbol 屬性可以用 Object.getOwnPropertySymbols()。

以上就是Object.keys 詭異特性示例詳解的詳細(xì)內(nèi)容,更多關(guān)于Object.keys 詭異的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論