JavaScript数据类型II 对象

对象(object)

对象(object)是JavaScript语言的核心概念,也是最重要的数据类型。简单来说,对象就是一组键值对(key -value)的集合,是一种无序的复合数据集合。[1]


  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'})    
    
  2. Tips🎯

    • 'name' : 'Yea Miko'即是一组键值对(Key-Value)'name'是Key,即对象的属性名'Yea Miko'是Value,即对象的属性值
    • 所有的键名(Key)都是字符串。它们并非标识符,可以包含任意字符。
    • 'name'中的''是可以省略的,一旦省略,就只能声明符合标识符规则(字母或数字或下划线_或美元符号$)但可以以数字为开头的键名。
    • 就算省略了'',键名仍旧是字符串
    • 如果属性名由科学记数法、非十进制数等等充当,JavaScript会优先计算它们的结果并转换为可读十进制数,再将其转化为字符串作为属性名
    • 如果属性名由变量充当,则需要加[ ]表示,例[name]
    • 每个对象都有一个隐藏属性,隐藏属性存储着原型的地址。

相关操作


  1. 删除对象的属性

    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属性,值肯定为空啦😜
    
  2. 查看对象的属性

     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)
    //查看自身所有属性+隐藏的共有属性(原型)
    

    这里简单区分一下inhasOwnProperty的区别,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',查看单个属性值
    
  3. 修改或增加对象的属性

    修改与增加基本同义:已有属性则改,无该属性则增。

     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为原型构造对象
    

    如果一定要对原型进行修改,那么应该从一开始声明对象时就进行,不要“半路出家”,不然可能会乱成一锅粥😅

    原型仍旧存在一些疑问的话,可以看看这篇唠叨(目前正在施工中👷,施工完成后会附上链接)