对象(object)
对象(object)是JavaScript语言的核心概念,也是最重要的数据类型。简单来说,对象就是一组键值对(key -value)的集合,是一种无序的复合数据集合。[1]
-
对象的声明方式
1 2 3 4 5 6 7 8
//正式的声明方式 let obj = new Object ( { 'name' : 'Yea Miko' , 'weapon' : 'Catalyst'} ) //我们常用的声明方式 let obj = { 'name' : 'Yea Miko' , 'weapon' : 'Catalyst'} //匿名声明 console.log({'name' : 'Yea Miko' , 'weapon' : 'Catalyst'})
-
Tips🎯
'name' : 'Yea Miko'
即是一组键值对(Key-Value)。'name'
是Key,即对象的属性名。'Yea Miko'
是Value,即对象的属性值。- 所有的键名(Key)都是字符串。它们并非标识符,可以包含任意字符。
'name'
中的''
是可以省略的,一旦省略,就只能声明符合标识符规则(字母或数字或下划线_
或美元符号$
)但可以以数字为开头的键名。- 就算省略了
''
,键名仍旧是字符串。 - 如果属性名由科学记数法、非十进制数等等充当,JavaScript会优先计算它们的结果并转换为可读十进制数,再将其转化为字符串作为属性名。
- 如果属性名由变量充当,则需要加
[ ]
表示,例[name]
。 - 每个对象都有一个隐藏属性,隐藏属性存储着原型的地址。
相关操作
-
删除对象的属性
1 2 3 4 5 6 7 8
let obj = { name : 'Yea Miko' , weapon : 'Catalyst'} delete obj.name delete obj['name'] //删除对象obj的name属性(key&value全部删除) obj.name = undefined //将obj的name属性值赋值为undefined,即删除了name的value
当我们对对象属性进行删除后,要判断是否删除成功,可以使用
in
来判断1 2 3 4 5
let obj = { name : 'Yea Miko' , weapon : 'Catalyst'} delete obj.name 'name' in obj //返回false,则意味name属性不在对象obj中,删除成功
1 2 3 4 5 6 7 8 9
let obj = { name : 'Yea Miko' , weapon : 'Catalyst'} obj.name = undefined 'name' in obj && obj.name === undefined //返回true,则意味着name属性在对象obj中,但值为空 //单一的obj.x === undefined并不能判断x是否为obj的属性,如 obj.element === undefined //返回true,因为对象里都没有element属性,值肯定为空啦😜
-
查看对象的属性
1 2 3 4 5 6 7 8 9 10 11 12 13
let obj = { name : 'Yea Miko' , weapon : 'Catalyst'} Object.keys(obj) //返回['name' , 'weapon'],查看自身所有属性名 Object.values(obj) //返回['Yea Miko', 'Catalyst'],查看自身所有属性值 Object.entries(obj) //返回[Array(2), Array(2)],查看自身可枚举属性的键值对数组 console.dir(obj) //查看自身所有属性+隐藏的共有属性(原型)
这里简单区分一下
in
与hasOwnProperty
的区别,in
无法判断属性为自身还是共有属性, 但hasOwnProperty
可以。1 2 3 4 5 6 7
let obj = { name : 'Yea Miko' , weapon : 'Catalyst'} 'toString' in obj //返回true,toString在对象obj中 obj.hasOwnProperty(toString) //返回false,toString不是对象obj的自身属性,是从原型中携带而来的共有属性。
时刻提醒自己属性名是字符串这一重要信息,才会在以下的列举中不会出错。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
name = 'fox' let obj = { [name] : 'Yea Miko' , weapon : 'Catalyst'} obj.name //返回undefined //该语法下"."后加的应该是真实的属性名fox(为字符串),而非变量名 obj[name] //返回'Yea Miko',查看单个属性值 obj.fox //返回'Yea Miko',查看单个属性值 obj['fox'] //返回'Yea Miko',查看单个属性值
-
修改或增加对象的属性
修改与增加基本同义:已有属性则改,无该属性则增。
1 2 3 4 5 6 7 8 9 10 11 12 13
let obj = { name : 'Yea Miko'} obj.name = 'Yea Sakura' obj['name'] = 'Yea Sakura' obj.element = 'Electro' //无element属性,则新增 //若通过变量更改 person = 'name' obj[person] = 'Yea Sakura' //批量赋值 Object.assign(obj , { weapon : 'Catalyst' , rarity : 5 , element : 'Electro' })
如果涉及到与原型有关的修改操作……🤔
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
let obj1 = {} let obj2 = {} obj1.toString = 'chocolate' obj2.toString === 'chocolate' //返回false,可以见得我们无法通过一层去修改原型 obj1.__proto__.toString = 'chocolate' obj2.toString === 'chocolate' //返回true,我们通过这种把隐藏属性调取出来并进行修改的操作,改变了共有的原型 //但是这是不推荐的写法,如果有修改的必要推荐使用⬇️ Object.prototype.toString = ' chocolate' obj1.toString === 'chocolate' obj2.toString === 'chocolate' //返回true
但是我们一般不要修改原型,否则会引来各种意想不到的崩溃😡
1 2 3 4 5 6 7 8 9 10 11 12
let obj1 = {} let obj2 = {} obj1.__proto__ = obj2 'toString' in obj1 //返回true //虽然我们修改了obj1的隐藏属性,指向了对象obj2 //但是因为对象obj2中仍然有原型存在,我们仍旧可以调用toString //这仍旧是不推荐的写法,如果想要声明一个拥有此类原型链的对象⬇️ let obj2 = {} let obj1 = Object.create(obj2) //以obj2为原型构造对象
如果一定要对原型进行修改,那么应该从一开始声明对象时就进行,不要“半路出家”,不然可能会乱成一锅粥😅
对原型仍旧存在一些疑问的话,可以看看
这篇唠叨(目前正在施工中👷,施工完成后会附上链接)