删除属性

一般 delete 只能删属性,如果要删其他的最好不要用delete

删除属性的语法

  1. /* 语法1 */
  2. delete obj.xxx
  3. /* 语法2 */
  4. delete obj['xxx']

区分「属性值为 undefined」和「不含属性名」

  • 定义一个名为 obj 的对象,并给它属性 name ,属性值为 undefined

    1. var obj = {
    2. 'name': undefined
    3. }
  • 此时,obj 含有属性 namename 并没有被删除,只不过其值为 undefined

  • 'xxx' in obj && obj.xxx === undefine:含有属性名,但是值为undefined

image.png

【注意】**obj.xxx === undefined**

  • 不能断定 ‘xxx’ 是否为 obj 的属性
  • 这只能判断属性值,不能判断属性名,要判断属性名只能用 in

图示: image.png

如何检测是否为属性

  • 把属性名作为字符串,然后 in 这个对象即可。
  • 'xxx' in obj === false :检测 'xxx' 是否为对象 obj 的属性

查看所有属性(读属性)

查看自身所有属性

  1. Object.keys(obj) // 查看所有 key
  2. Object.values(obj) // 查看所有 value
  3. Object.entries(obj) // 查看所有 key 和 value

查看自身 + 共有属性

  1. console.dir(obj)
  • 或者自己依次用 Object.keys 打印出 obj.proto

    判断一个属性是自身还是共有的

    1. obj.hasOwnProperty('toString')
  • 如果为 false 就说明这个属性不是它自身的,有可能是原型上的,也有可能不存在。

查看单个属性

  1. /* 中括号语法 */
  2. obj['key']
  3. /* 点语法 */
  4. obj.key
  5. /* 坑新人语法 (若属性名是一个变量) */
  6. obj[key]

优先使用中括号语法

  • 点语法会误导人以为 key 不是字符串
  • 确定不会弄混两种语法后,再改用点语法

【注意】:

  • obj.name 等价于 obj['name']
  • obj.name 不等价于 obj[name]
  • 简单来说,这里的 name 是字符串,而不是变量
  • let name = 'frank' obj[name] 等价于 obj['frank']
  • 而不是 ~~obj['name'] 和 obj.name~~


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

  • 读属性的时候会看隐藏属性对应的原型
  • 写属性(改/增)的时候不走原型,只能写到属性自身身上

直接赋值

  1. /* 语法一 */
  2. obj.name = 'tk'
  3. /* 语法二 */
  4. obj['name'] = 'tk'
  5. /* 神奇的写法 */
  6. obj['na' + 'me'] = 'tk'
  7. /* 使用变量的写法 */
  8. let key = 'name'
  9. obj[key] = 'tk'

错误的语法:

  1. obj[name] = 'tk' // 错,因 name 是变量,值不确定
  2. let key = 'name'; obj[key] = 'frank' // 正确写法
  3. let key = 'name'; obj.key = 'frank' // 错,因为 obj.key 等价于 obj['key']

批量赋值

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

示例:
image.png

修改或增加共有属性

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

  • let obj = {}, obj2 = {} // 共有 toString
  • obj.toString = 'xxx' 只会在改 obj 自身属性
  • obj2.toString 还是在原型上

    硬要修改或增加原型上的共有属性

  • obj.__proto__.toString = 'xxx' // 不推荐用 proto

  • Object.prototype.toString = 'xxx'
  • 一般来说,不要修改原型,会引起很多问题

修改隐藏属性

不推荐使用 proto

  1. let obj = {name:'frank'}
  2. let obj2 = {name: 'jack'}
  3. let common = {kind: 'human'}
  4. obj.__proto__ = common
  5. obj2.__proto__ = common

推荐使用 Object.create

  1. let obj = Object.create(common)
  2. obj.name = 'frank'
  3. let obj2 = Object.create(common)
  4. obj2.name = 'jack'
  5. 规范大概的意思是,要改就一开始就改,别后来再改

原型和共有属性的区别?

  • 原型是对象
  • 共有属性是属性
  • 原型包含了所有共有属性(共有属性依附在原型这个对象上) | 红圈为原型
    蓝线画的是一个个共有属性 | image.png | | —- | —- |

总结

  • 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'] = 'xxx'
  • 改原型:obj.__proto__ = common
  • 改原型:let obj = Object.create(common)
  • 所有 proto 代码都是强烈不推荐写的

  • 基本同上:已有属性则改;没有属性则增。

部分资料来源:饥人谷 - 方方老师