关于JS中Object对象的key及key的排序

首先,JavaScript中Object对象的key均为String或Symbol类型的值。

(对于使用Symbol类型的值作为Object对象键的部分,这个并不会进行讨论)

不过Object对象可以接受任意类型的值作为它的key,原因在于,我们为某个Object对象设定key的过程中会触发JavaScript的隐式类型转换机制(调用相应的toString()方法)。

 

我们先来尝试用各种类型的数值作为实验对象的key值:

// 实验对象
var _test_o_ = {};

 

1. String

_test_o_['mark'] = 'sign';
// 或者直接使用 . 操作符
_test_o_.mark = 'sign';

console.log(_test_o_);
// { mark: 'sign' }

2. Number

_test_o_[0] = 0;

console.log(_test_o_);
// { mark: 'sign', '0': 0 }
// 注:想访问'0'键的值,可以通过 _test_o_['0'] 或者 _test_o_[0]

3. Boolean

_test_o_[true] = true;

console.log(_test_o_);
// {
//   'mark': 'sign',
//   '0': 0,
//   'true': true,
// }

4. Undefined

_test_o_[undefined] = undefined;

console.log(_test_o_);
// {
//   'mark': 'sign',
//   '0': 0,
//   'true': true,
//   'undefined': undefined,
// }

5. Null

_test_o_[null] = null;

console.log(_test_o_);
// {
//   'mark': 'sign',
//   '0': 0,
//   'true': true,
//   'undefined': undefined,
//   'null': null,
// }

6. Symbol

var symbol = Symbol();
_test_o_[symbol] = 'symbol';

console.log(_test_o_);
// {
//   ...
//   Symbol(): 'symbol',
// }

7. BigInt

var bn = 1n;
_test_o_[bn] = '1n';

console.log(_test_o_);
// {
//   ...
//   Symbol(): 'symbol',
//   '1': '1n',
// }

8. Object

var prop = {};
_test_o_[prop] = '{}';

console.log(_test_o_);
//
// {
//   ...
//   Symbol(): 'symbol',
//   '1': '1n',
//   [object Object]: '{}',
// }

9. Array

var arr = [];
_test_o_[arr] = '[]';

console.log(_test_o_);
// {
//   ...
//   Symbol(): 'symbol',
//   '1': '1n',
//   '[object Object]': '{}',
//   '': '[]',
// }

10. Map

var map = new Map();
_test_o_[map] = 'map';

console.log(_test_o_);
// {
//   ...
//   Symbol(): 'symbol',
//   '1': '1n',
//   '[object Object]': '{}',
//   '': '[]',
//   '[object Map]': 'map',
// }

11. 自定义类

class AClass {
  toString() {
    return 'a-class-inst';
  }
}
_test_o_[new AClass()] = 'instance';

console.log(_test_o_);
// {
//   ...
//   Symbol(): 'symbol',
//   '1': '1n',
//   '[object Object]': '{}',
//   '': '[]',
//   '[object Map]': 'map',
//   'a-class-inst': 'instance',
// }

其余的数据类型,这里不再进行一一列举

 

以下,

关于Object对象的key的排序问题

1. key,全部为Number类型(或者可以被转换为有效数字的类型)且数字值属于非负整数

const nums = [2, 5, 1, 8, 7, 0];
const o = {};
for (const i of nums) {
  o[i] = i;
}

console.log(o);
// {
//   '0': 0,
//   '1': 1,
//   '2': 2,
//   '5': 5,
//   '7': 7,
//   '8': 8,
// }
const pseudoNums = ['2', '5', '1', '8', '7', '0'];
const o = {};
for (const i of pseudoNums) {
  o[i] = i;
}

console.log(o);
// {
//   '0': '0',
//   '1': '1',
//   '2': '2',
//   '5': '5',
//   '7': '7',
//   '8': '8',
// }

可以看出,这种情况下的keys,在对象中的位置会变得有序。

这个性质在解决一些特定问题中会发挥很强的辅助作用,记得mark。

 

2. key, 全部为String类型

const o = {};
for (const i of ['b', 'z', 'a', 'q', 'h', 'f']) {
  o[i] = i;
}

console.log(o);
// {
//   'b': 'b',
//   'z': 'z',
//   'a': 'a',
//   'q': 'q',
//   'h': 'h',
//   'f': 'f',
// }

这种情况,key的次序就是其当时的插入顺序。

 

3. 混合 情况1 和 情况2

const o = {};
for (const i of [2, 5, 1, 8, 7, 0, '11', '9', '4', 'b', 'z', 'a', 'q', 'h', 'f']) {
  o[i] = i;
}

console.log(o);
// {
//   '0': 0,
//   '1': 1,
//   '2': 2,
//   '4': '4',
//   '5': 5,
//   '7': 7,
//   '8': 8,
//   '9': '9',
//   '11': '11',
//   'b': 'b',
//   'z': 'z',
//   'a': 'a',
//   'q': 'q',
//   'h': 'h',
//   'f': 'f',
// }

可以看出数字或伪数字类型的key依然会变得有序,其他的key仍是与其插入的次序一致。

关于数字或伪数字类型key的访问特性:

var obj = { 2: 'a' };

obj.hasOwnProperty('2');
// output: true

obj.hasOwnProperty(2);
// output: true

obj['2']; // 'a'
obj[2]; // 'a'

 

posted @ 2022-08-25 22:07  樊顺  阅读(4895)  评论(0编辑  收藏  举报