键: 值
)的形式体现,键就是属性名,值就是属性值。{}
包围。const empty = { }
const robot = {
name: 'balance car',
priceExpected: 899,
isChecked: true,
parts: ['balanceSys', 'dynamicalSys', 'model'],
agency: { warranty: '2Y', address: ['A city', 'B city'] },
forward: function () {
console.log('前进');
},
backward: function () {
console.log('后退');
},
brake: () => {
console.log('刹车')
},
turnLeft() {
console.log('左转');
},
turnRight() {
console.log('右转');
}
};
属性是属性名与属性值的结合(属性=属性名+属性值
)。
String
或 Symbol
两种类型;
Symbol
外都被转成字符串了,任何对象作为属性名时,被转成字符串 [object Object]
;getter
)、取值器(setter
)等例外。in
,语法是:key in object
。属性值的访问(获取、更新等):
obj.key
点链式;obj['key']
方括号式,具有数字特征的属性名,只能使用此式。let person1 = {
1: 'id',
name: 'Peter',
gender: 'Man',
habit: { sport: 'jog', game: 'LOL' }
_age: 28,
'birth year': 2000, // 存在空格,需要引号
get age() { return this.age; },
set age(age) { this.age = age; },
}
'name' in person1 // true
person1.1 // 报错 person1[1]/person1['1']是允许的
person1['name'] // 'Peter' --- [] 式
person1.age // 28 --- . 式
person1.gender = 'Woman' // 将属性更新
person1.habit.sport = 'football'
.
式添加属性;[]
式添加属性。let a = 10, b = 20, c = 30;
let obj = {
a: a, // 第一个 a是属性名,第二个是属性值(=10、引用)
sum() { let s = 0; for (let k in this) if(k != 'sum') s += this[k]; return s; }
}
obj.sum // 10
obj.b = b;
obj['c'] = c
obj.sum // 60
[]
将其包围。let what = prompt("输入你要的属性名?", "what");
let value = prompt("输入你要的属性值?", "1");
let o = {
[1 + 2]: '三', // 1+2是一个表达式, 计算结果3 是最终属性名
[what]: value // what 是一个变量, 它的右边是表达式, 输入的提示词是最终的属性名
}
/* 如果what==name,value=joe */
o // { 3: '三', name: 'joe' }
o.name // 'joe'
Symbol(描述字符串)
创建唯一标识符;[]
包围;obj[key]
添加,不能通过点链式 obj.key
进行添加;let id1 = Symbol('ID');
let id3 = Symbol('ID');
let o = {
a: 1,
b: 2,
[id1]: 1,
[Symbol('id')]: 2
}
o[id3] = 3
o // { a: 1, b: 2, Symbol('ID'): 1, Symbol('ID'): 2, Symbol('ID'): 3 }
Object.getOwnPropertyDescriptor(object, key)
进行读取;let o = { a: 1, b: 2 };
Object.getOwnPropertyDescriptor(o, 'a')
/*
{
value: 123, // 值
writable: true, // 可写
enumerable: true, // 可枚举
configurable: true // 可配置
}
*/
enumerable: false
)的属性:
for...in
循环遍历:只遍历对象自身的和继承的可枚举的属性(不含Symbol属性);Object.keys()
:返回对象自身的所有可枚举的属性的键名(不含Symbol属性);JSON.stringify()
:只串行化对象自身的可枚举的属性(不含Symbol属性);Object.assign()
:ES6、只拷贝对象自身的可枚举的属性。for in
循环遍历,遍历(对象自身的、继承的)可枚举的属性名;Object.keys(obj)
,返回一个数组,包含(对象自身的)可枚举的属性名;Object.getOwnPropertyNames(obj)
,数组,包含(对象自身的)除 Symbol 外的属性名;Object.getOwnPropertySymbols(obj)
,数组,包含(对象自身的)Symbol 属性名;Reflect.ownKeys(obj)
,返回一个数组,包含(对象自身的)所有属性名。/* 只有 for in 循环遍历,会遍历继承的属性 */
const obj = { c: 3 };
let o = { a: 1, b: 2, [Symbol('id')]: 1 }
o.__proto__ = obj
o.c // 3
for (let k in o) console.log(k) // 1, 2, 3
Object.getOwnPropertySymbols(o) // [Symbol('id')]
:
与 function
;this
指向的是,当前代码运行时的对象;let dog1 = {
name: 'Kitty';
bark() { console.log(`Dog ${this.name} is barking!`) } // this 指向 dog1
}
let dog2 = {
name: 'Gimmy';
bark() { console.log(`Dog ${this.name} is barking!`) } // this 指向 dog2
}
new
、this
引导实现:new
开辟一个对象空间,this
指向并绑定对象,调用时需要 new
引导;new
引导,没有开辟对象空间,则 this
可能指向全局对象,所有创建的属性也归属之;return
语句,则返回对应的值。function Pet(type, name) {
// this = {} // 隐式实现
this.type = type; // 'dog'? or 'cat'? or anyelse
this.name = name;
this.bio = function () {
console.log(`${this.name} is my ${this.type} pet!`);
};
// return this; // 隐式实现
// return { a: 1, b: 2 } // 撒子或疯子会这样写
}
let pet = new Pet('dog', '二哈'); // pet = { type: 'dog', .... }
let p = Pet('cat', '咪咪'); // p = undefined 需要new开辟对象空间
/* 传统的构造对象的函数 */
function Pet(type, name) {
const pet = {};
pet.type = type; // 'dog'? or 'cat'? or anyelse
pet.name = name;
pet.bio = function () {
console.log(`${pet.name} is my ${pet.type} pet!`);
};
return pet;
}
键
)关联到数据(值
)的过程;键
指定对应的 值
(就像指针指向地址)实现;for in
遍历以拷贝到数据进行赋值,另外就是使用 Object.assign
将源对象的数据拷贝赋值给目标对象,两方法近似等价;lodash
库的 _.cloneDeep(obj)
。let o1 = { a: 1, b: 2 }
let o2 = o1
o1 == o2 // true
o1 === o2 // true
let obj1 = { a: 0 }, obj2 = { a: 0 };
obj1 == obj2 // false 不是同一个数据,尽管内容一样
/* 拷贝赋值 Object.assign(dest, [src1, src2, ...]) src个数0或1或多个 */
let obj3 = { a: 1, b: 2 };
let obj = Object.assign(obj1, obj3);
obj // { a: 1, b: 2 } 相同的属性被覆盖
/* 深层拷贝赋值 */
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>
?.
。如果有实在的属性(!=null,undefined),就继续引用;否则停止并返回 undefined
。?.
使得其前面的数据作为判断的主体,判断主体需要事先声明,主体不存在(未定义或为空等情况),会“短路”马上停止。let resident = {};
user.address ? user.address.street ? user.address.street.name : null : null // 通过条件判断
resident.address && resident.address.street && resident.address.street.name // 通过逻辑表达式
/* 下面使用可选链 */
resident?.address?.street?.name
resident.address?.street?.name // address 这个属性可以确定
?.()
,面向方法(函数),不确定是否可调用;?.[]
方括号式,和点链式 ?.
一样访问不确定的属性。let o = {
a: 1,
b: 2,
s() { return this.a + this.b; }
}
o.s?.() // 3,s 是o的方法,可以被调用
o.x?.() // undefined,o.x===undefined
o.a?.() // 报错,a是确定的,不可被调用的属性
o?.['a'] // 1
o?.['c'] // undefined