JavaScript 对象基本用法

222 阅读5分钟

一、对象基础总结

增删改查总结

  • delete obj['name']
    'name' in obj //false 代表成功删除
    obj.hasOwnProperty('name') //false
    
  • Object.keys(obj)
    console.dir(obj)
    obj['name']
    obj.name //记住这里的name是字符串
    obj[name] // 记住这里的name是变量
    
    • 改自身属性:obj['name'] = 'jack'

    • 批量改自身属性:Object.assign(obj,{age:18,...})

    • 改共有属性: obj.__proto__['toString'] = 'xxx'

    • 改共有属性推荐的方法 :Object.prototype['toString']

    • 改原型: obj.__proto__['toString'] = 'xxx'

    • 改原型推荐的方法 : let obj = Object.create(common)

    • 注意:所有__proto__代码都是强烈不推荐写的

    • 基本跟改的方法是一样的

    • 有的属性通过上面的方法就是改,没有的属性通过上面的方法就是新增属性

写法

  • let obj = {'name':'jackey','age':18} 简单的写法,一般用这个

  • let obj = new Object({'name': 'jackey','age': 18}) 正规的写法

  • console.log({'name': 'jackey','age': 18}) 匿名对象

细节

  • 键名是字符串,不是标识符,可以包含任意字符

  • 引号可以省略,省略之后就只能写标识符

  • 就算引号省略了,键名也还是字符串(重要)

  • Object.keys(对象)能打印出该对象的所有键值对

1.属性名和属性值

  • 每一个key都是对象的属性名 (property)

  • 每一个value都是对象的属性值

奇怪的属性名

1.所有属性名会自动变成字符串

  •   let obj = {
      1:'a',
      3.2:'b',
      1e2:'true',
      1e-2:'true',
      .234:'true',
      0xff:'true'
      }
      
      Object.keys(obj)
      =>['1','3.2','100','0.01','0.234','225']
    

    JS会先换算,再把属性名变成字符串(有点蛋疼)

  • 由此推论,加引号是最保险的写法

2.变量作为属性名

  • 之前都用常量做属性名

  • 如果用变量做属性名应该如下

    let p1 ='name'
    let obj{p1:'frank'} // 这样写,属性名为'p1'
    let obj{[p1]:'frank'} // 这样写,属性名为'name'
    
  • 对比

    1. 不加[]的属性名会自动变成字符串

    2. 加了[]的属性名则被JS引擎当成变量值

    3. 值如果不是字符串,也会被自动变成字符串

对象的隐藏属性

a.隐藏属性

  • JS中每一个对象都有一个隐藏属性

  • 这个隐藏属性储存着其共有属性组成的对象的地址

  • 这个共有属性组成的对象叫原型

  • 隐藏属性储存这原型的地址

b.代码示例

  •  let obj = {}
     obj.toString() // 不会报错
    
  • 因为obj的隐藏属性对应的对象上有toString这个属性

超纲的知识

a.除了字符串,symbol也能做属性名

let a = symbol()
let obj = {[a]:'Hello'}

b.用途

  • 目前,暂时没用,要到很久以后可能才会用到

  • 在学习(迭代)的时候会用到

  • 知道有这么个东西就行了

二、对象的增删改查

1. 删除属性

  • delete obj,xxxdelete boj['xxx'] 就能删除objxxx属性

一定区分属性值为undefined不含属性名

  • 不含属性名

    • 'xxx' in obj === false
  • 含有属性名,但是值为undefined

    • 'xxx' in obj && obj.xxx === undefined
  • 删除成功与否

    • 'xxx' in obj 若结果是 false 就代表删除成功了

    • 必须要加引号,因为属性名始终是字符串

delete 只能删除属性,不能删除对象

2. 查看属性

(1)查看所有属性

  • (a).查看自身所有属性

    Object.keys(obj)

  • (b).查看自身+共有属性

    console.dir(obj)

    或者依次用Object.keys打印出obj.__proto__

  • (c).查看自身属性值

    Object.Values(obj)

  • (d).查看自身所有属性名和属性值

    Object.entries(obj)

(2).判断一个属性是自身的还是共有的

obj.hasOwnProperty('toString')

属性是否共有

  • 'xxx' in obj 区别

    • 'xxx' in obj 不管属性是自身属性还是共有属性,只要有xxx这个属性就会返回 true

    • obj.hasOwnProperty('xxx') 只有这个xxx属性是自身属性,才返回 true

(3)查看单一属性

  • 两种方法

    1. 中括号语法:obj['key']

    2. 点语法:'obj.key'

    3. 容易误解的语法:obj[key] 变量key的值,一般不为'key'

  • 优先使用中括号法,因为点语法会误导新手,等确定不会搞混两种语法,再改用点语法

(4)需要注意的情况

第一种情况

obj.name 等价于 obj['name']
obj.name 不等价于 obj[name] 简单的说,这里的name是字符串,不是变量

第二种情况

let name = 'jackey'
obj[name]等价于obj['jackey']
不是obj['name']和obj.name
千万不要记错了

4fb4804795e683b39e26d4050a1fff3.png

3.修改或增加属性(写属性)

(1)直接赋值

  • let obj = {name:'jackey'}这里的 name 是字符串

  • obj.name = 'jackey' 这里的 name 是字符串

  • obj['name'] = 'jackey'

  • obj[name] = 'jackey' 这样是错的,因为这里的name是变量,值不确定

  • obj['na'+'me'] = 'jackey'

(2)批量赋值

  • Object.assign(obj,{age:18,gender:'man'})

  • 这时ES6的心属性

(3)修改或增加共有属性

  • 无法通过自身修改或增加共有属性

    • let obj = {},obj2 = {}共有属性toString

    • obj.toString = 'xxx' 只会更改或添加obj这个对象的自身属性

    • obj2.toString 还是在原型上

  • 如果你非要修改或增加共有属性

    • obj.__proto__.toString = 'xxx' 任何时候都不推荐用__proto__

    • Object.prototype.toString = 'xxx'

    • 一般来说,不要直接修改共有属性,会引起许多问题,如果要修改请直接在对象声明前给一个新的原型链

(4)修改隐藏属性

  • a.不推荐用__proto__

    let obj = {name:'jackey'}
    
    let obj2 = {name:'frank'}
    
    let common = {kind:'human'}
    
    obj.__proto__ = common
    
    obj2.__proto__ = common
    
    这样obj和obj2的隐藏属性就存了common这个属性的地址
    
  • b.推荐使用Object.create

    let obj = Object.create(common)
    
    obj.name = 'jackey'
    
    let obj2 = Object.create(common)
    
    obj2.name = 'frank'
    
    这样和上面的实现效果是一样的,但性能比上面好
    
  • 规则的意思是,要改一开始声明对象的时候你就改,不要后面再来改

三、原型补充

1.每一个对象都有原型

  • 原型是存着对象的共有属性的

  • 比如obj的原型就是一个对象

  • obj.__proto__存着这个对象的地址

  • 这个对象里有toString/constructor/valueOf 等共有属性

2.对象的原型也是对象

  • 所以对象的原型也有原型

  • obj = {}的原型即为所有对象的原型

  • 这个原型包含所有对象的共有属性,是对象的根

  • 这个原型也有原型,存的是null