Автор этой статьи:Berwin, Член рабочей группы Performance W3C, старший инженер-интерфейс 360 навигации. Ранний пользователь Vue.js, автор «Введение в Vue.js» (в публикации).Ссылка в блоге
На днях друг задал мне вопрос: почемуObject.keys
Возвращаемое значение будет автоматически отсортировано?
Пример такой:
const obj = {
100: '一百',
2: '二',
7: '七'
}
Object.keys(obj) // ["2", "7", "100"]
А следующий пример не сортирует автоматически?
const obj = {
c: 'c',
a: 'a',
b: 'b'
}
Object.keys(obj) // ["c", "a", "b"]
Когда друг задал мне этот вопрос, я долго не мог на него ответить. Так что я проверилСпецификация ECMA262, и прочитав статью на этот счет, я понял, почему произошло такое странное.
Поэтому я написал эту статью, чтобы подробно представить, когдаObject.keys
Что происходит внутри, когда он вызывается.
1. Ответы
Подводя итог вышеизложенному вопросу,Object.keys
Внутренне на основе имени свойстваkey
Типы выполняют различную логику сортировки. Есть три случая:
- Если тип имени свойства
Number
,ТакObject.keys
Возвращаемое значение соответствуетkey
Сортировать от меньшего к большему - Если тип имени свойства
String
,ТакObject.keys
Возвращаемое значение сортируется в порядке возрастания по времени создания свойства. - Если тип имени свойства
Symbol
, то логичноString
такой же
Это объясняет проблему выше.
Ниже мы подробно знакомимObject.keys
Когда звонят, что происходит за кулисами.
2. КогдаObject.keys
что происходит за кулисами, когда это называется
когдаObject.keys
функция с параметрамиO
При вызове выполняются следующие действия:
Шаг 1: Преобразуйте параметры вObject
тип объекта.
Шаг 2: Получите список свойств через преобразованный объектproperties
.
Примечание. Список свойств
properties
имеет тип Список (Тип спискадаКанонический тип ECMAScript)
Шаг 3: Перечислите свойства типа спискаproperties
Преобразуйте в массив, чтобы получить окончательный результат.
Спецификация определяет это так:
- передача
ToObject(O)
присвоить результат переменнойobj
- передача
EnumerableOwnPropertyNames(obj, "key")
присвоить результат переменнойnameList
- передача
CreateArrayFromList(nameList)
получить окончательный результат
2.1 Преобразование параметров в объект (ToObject(O)
)
ToObject
Операция изменяет параметры в соответствии с таблицей нижеO
Преобразование в значение типа Object:
Тип параметра | результат |
---|---|
Undefined | выдает TypeError |
Null | выдает TypeError |
Boolean | возвращает новый логический объект |
Number | возвращает новый объект Number |
String | возвращает новый объект String |
Symbol | Возвращает новый объект Symbol |
Object | Возврат объекта напрямую |
потому чтоObject.keys
внутриToObject
операция, такObject.keys
На самом деле могут быть получены и другие типы параметров.
В приведенной выше таблице указано, как параметры различных типов будут преобразованы в тип объекта.
Мы можем просто написать несколько примеров, чтобы попробовать:
попробуй сначалаnull
Будет ли он сообщать об ошибке:
фигура 1Object.keys(null)
Как показано на рисунке 1, действительно сообщается об ошибке.
Далее пробуем эффект чисел:
фигура 2Object.keys(123)
Как показано на рисунке 2, возвращается пустой массив.
Почему он возвращает пустой массив? См. рисунок 3:
изображение 3new Number(123)
Как показано на рис. 3, возвращаемый объект не имеет каких-либо извлекаемых свойств, поэтому возвращение пустого массива также является нормальным явлением.
Затем мы снова пробуем эффект String:
Рисунок 4Object.keys('我是Berwin')
На рис. 4 мы увидим, что возвращаются некоторые числа строкового типа, поскольку объект String имеет извлекаемые свойства, см. рис. 5:
Рисунок 5new String('我是Berwin')
Поскольку объект String имеет извлекаемые свойства, имена свойств объекта String извлекаются и возвращаются в виде списка.
2.2 Получить список свойств (EnumerableOwnPropertyNames(obj, "key")
)
Процесс получения списка свойств имеет множество деталей, наиболее важной из которых является вызов внутреннего метода объекта.OwnPropertyKeys
получить объектownKeys
.
Примечание: в это время
ownKeys
Тип представляет собой тип списка, который используется только для внутренней реализации.
затем объявите переменнуюproperties
, тип также является типом списка, и циклownKeys
добавить каждый элемент вproperties
Список.
в конце концовproperties
вернуть.
Вам может быть интересно, почему ownKeys уже является результатом, почему вы перебираете элементы списка в цикле?
properties
середина.Это связано с тем, что операция EnumerableOwnPropertyNames используется не только для API Object.keys, но и имеет внутри себя некоторые другие операции, но API Object.keys не используется, поэтому этот шаг кажется излишним.
Таким образом, дляObject.keys
Для этого API самым важным в списке свойств является вызов внутреннего методаOwnPropertyKeys
получатьownKeys
.
По сути, это внутренний метод.OwnPropertyKeys
Определяет порядок атрибутов.
оOwnPropertyKeys
методECMA-262Он описывается таким образом:
когдаO
внутренний методOwnPropertyKeys
При вызове выполняются следующие шаги (фактически один шаг):
Return ! OrdinaryOwnPropertyKeys(O).
а такжеOrdinaryOwnPropertyKeys
Оговаривается так:
- объявить переменную
keys
Значение представляет собой пустой список (тип списка) - Отсортируйте свойства каждого числового типа в порядке возрастания значения и добавьте их в
keys
середина - Отсортируйте свойства каждого типа String в порядке возрастания времени создания и добавьте их в
keys
середина - Отсортируйте атрибуты каждого типа символов в порядке возрастания времени создания и добавьте их в
keys
середина - Буду
keys
вернуть(return keys
)
Вышеприведенное правило не только оговаривает порядок возврата разных типов, но также оговаривает, что если тип атрибута объекта является числом, а символ смешан с символом, то порядок возврата всегда сначала число, затем строка , и, наконец, Символ.
Например:
Object.keys({
5: '5',
a: 'a',
1: '1',
c: 'c',
3: '3',
b: 'b'
})
// ["1", "3", "5", "a", "c", "b"]
Хотя правила упорядочения атрибутов указываютSymbol
порядок, а по фактуObject.keys
в конце концовSymbol
Свойства типа отфильтровываются. (Причина в том, что правило порядка не просто даетObject.keys
использование API, это общее правило)
2.3 Преобразуйте тип списка в массив, чтобы получить окончательный результат (CreateArrayFromList( elements )
)
Теперь, когда у нас есть список свойств объекта, последний шаг — преобразовать список свойств типа List в тип Array.
Преобразование списка свойств типа List в тип Array очень просто:
- Сначала объявить переменную
array
, значение представляет собой пустой массив - Прокрутите список свойств, добавляя каждый элемент в
array
середина - Буду
array
вернуть
3. Это правило упорядочения также применяется к другим API.
Описанные выше сопоставления также применяются к следующим API:
Object.entries
Object.values
-
for...in
цикл Object.getOwnPropertyNames
Reflect.ownKeys
Примечание. В дополнение к вышеуказанному API
Reflect.ownKeys
, другие APISymbol
Введите свойства для фильтрации.