JavaScript 对象
JavaScript 对象 Object 是一系列属性的集合;每个属性都是一个键值对,key 的类型为字符串,value 可以为任何类型
创建对象
{}:对象字面量方式new Object():构造函数- 输入参数为空,或者
null、undefined会创建返回一个空对象; - 输入参数为对象,则直接返回该对象,
var obj = {a: 1}; obj === new Object(obj);// true; - 传入参数为原始类型,则返回该值的包装类;
- 通过构造函数与字面量写法是等价的;
- 输入参数为空,或者
Object.create(proto[, propertiesObject]):创建一个对象,并指定对象的原型proto:新创建对象的原型,可以为null或非基本类型包装对象以外的对象propertiesObject:可选参数,详细参考对象属性模型
```JS 字面量初始化 // 属性/函数简写 const a = 1; const b = 'string'; const c = {}; const o = { a, b, c, add(a, b) { return a + b; }, }
// 计算属性(ES2015) const firstName = 'Jordan'; const lastName = 'Mike';
const player = {
} console.log(player); // {Mike Jordan Team: 'Bulls'}
// getter setter方法 const o = { logs: [], get log() { return this.logs; }, set log(value) { this.logs.push(value); } } o.log = 'do job a'; o.log = 'do job b'; console.log(o.log); // ["do job a", "do job b"]
```JS
const person = {
isHuman: false,
printIntroduction: function() {
console.log(`My name is ${this.name}. Am I human? ${this.isHuman}`);
}
};
const me = Object.create(person);
const o = Object.create(Object.prototype, {
foo: {
writable: true,
configurable: true,
value: 'hello'
},
bar: {
configurable: false,
get: function() { return 10; },
set: function(value) {
console.log('Setting `o.bar` to', value);
}
}
});
对象属性模型
ECMAScript5 对对象的属性都提出了一个精确的模型描述,每个对象属性都有一个属性描述符对象,用来保存对象属性的描述,称为元信息。
查看对象属性元信息:可以通过Object.getOwnPropertyDescriptor(obj, prop)方法来获取
var obj = {a: 1};
Object.getOwnPropertyDescriptor(obj, 'a'); // { value: 1, writable: true, enumerable: true, configurable: true }
属性描述符有两种形式,数据描述符和存取描述符,一个描述符只能是其中一种,不能同时是两者:
- 数据描述符:有具体值的属性
value:属性的值,默认undefinedwritable:表示value的值是否可以改变(是否可以被赋值),默认falseenumerable:表示属性是否可枚举,默认false;详见对象属性遍历configurable:表示属性是否可以配置,默认false;如果为false则- 不可以使用
delete删除该属性 - 除了
value和writable之外的元信息都不能修改
- 不可以使用
- 存取描述符:由
getter和setter函数描述的属性get:属性的取值函数,默认undefinedset:属性的赋值函数,默认undefined
| configurable | enumerable | value | writable | get | set | |
|---|---|---|---|---|---|---|
| 数据描述符 | 可以 | 可以 | 可以 | 可以 | 不可以 | 不可以 |
| 存取描述符 | 可以 | 可以 | 不可以 | 不可以 | 可以 | 可以 |
修改/添加对象属性元信息:
Object.defineProperty(object, propertyName, attributesObject)Object.defineProperties(object, attributesObject)
var o = Object.defineProperty({}, 'a', {
value: 1,
writable: true,
enumerable: true,
configurable: true
});
Object.defineProperties({}, {
a: {
value: 1,
writable: true,
enumerable: true,
configurable: true
},
b: {
get:function() {
return this.a * 2;
}
},
});
- 设置
get/set属性后不能将writable设置为false,也不能设置value,否则会报错; enumerable、enumerable、configurable默认都为false;
对象属性遍历
- 可枚举属性遍历
for in:访问对象节对象自身及对象原型链上所有enumerable: true的属性,需要使用hasOwnProperty过滤原型链属性Object.keys(object):获取对象自身包含的enumerable: true的属性的字符串数组- 仅包含自身属性,不包含原型链继承属性
- 顺序和正常循环遍历对象时返回的顺序一致
- 类似的方法还有
Object.values()和Object.entries()
- 全部属性遍历
Object.getOwnPropertyNames(object): string[]:获取对象自身全部属性- 仅包含自身属性,不包含原型链继承属性
- 包括不可枚举属性但不包括
Symbol属性
Object.getOwnPropertySymbols(object): symbol[]:获取对象自身Symbol属性,与getOwnPropertyNames类似
属性是否可枚举:Object.prototype.propertyIsEnumerable(prop): boolean
var student = {
name: 'lee',
[Symbol('skill')]: '绘画',
[Symbol('skill')]: '演讲'
};
console.log(student.propertyIsEnumerable("name")) // true
console.log(student.propertyIsEnumerable("toString")) // false
console.log(Object.keys(student)) // ["name"]
console.log(Object.getOwnPropertyNames(student)) // ["name"]
console.log(Object.getOwnPropertySymbols(student)) // [Symbol(skill), Symbol(skill)]
删除对象属性
Object 自身没有提供方法删除其自身属性,必须使用delete操作符。delete操作成功后会返回true,否则返回false。
const obj = {a: 1};
Object.defineProperty(obj, 'b', {value: 2, writable: false});
console.log(obj); // {a: 1, b: 2}
console.log(delete obj.a); // true
console.log(delete obj.b); // false
console.log(obj); // {b: 2}
console.log(delete obj.a); // true
对象的状态控制
Object.preventExtensions(object):阻止对象继续添加属性Object.isExtensible(object):判断对象是否可以添加属性Object.seal(object):锁死对象,无法添加属性,也无法删除属性Object.isSealed(object):判断对象是否锁死Object.freeze(object):冻结对象,无法添加删除属性,也无法修改属性的值,注意:只能实现浅层冻结Object.isFrozen(object):判断对象是否冻结
对象实例方法
Object.prototype.valueOf():返回当前对象对应值,主要用途自动类型转换会调用该方法,可以重写覆盖该方法实现自己想要的效果Object.prototype.toString():返回当前对象对应字符串形式,可以自定义toString方法,得到想要的字符串形式Object.prototype.propertyIsEnumerable(attr):判断对象属性是否可枚举Object.prototype.hasOwnProperty(propName: string | symbol): boolean:判断某个属性是否为当前对象自身的属性Object.prototype.isPrototypeOf():判断当前对象是否为另一个对象的原型
Object.is(value1, value2): boolean
判断两个值是否为同一个值
- 和
==操作符的区别是不会进行强制类型转换 - 和
===操作符的区别是对正负零和NaN的判断逻辑
Object.is(25, 25); // true
Object.is('foo', 'foo'); // true
Object.is('foo', 'bar'); // false
Object.is(null, null); // true
Object.is(undefined, undefined); // true
Object.is(window, window); // true
Object.is([], []); // false
var foo = { a: 1 };
var bar = { a: 1 };
Object.is(foo, foo); // true
Object.is(foo, bar); // false
// Case 2: Signed zero
Object.is(0, -0); // false
Object.is(+0, -0); // false
Object.is(-0, -0); // true
Object.is(0n, -0n); // true
// Case 3: NaN
Object.is(NaN, 0 / 0); // true
Object.is(NaN, Number.NaN) // true
原型链
Object.getPrototypeOf(object):获取对象的原型对象。