语法
let obj = { 'name': 'frank', 'age': 17 }
let obj = new Object({ 'name': 'frank', 'age': 17 })
console.log('name': 'frank', 'age': 17)
- 键名是字符串,不是标识符,可以包含任意字符
- 引号可省略,省略之后就只能写标识符
- 就算引号省略了,键名也还是字符串(重要)
属性名:每个key 都是对象的属性名(property)
属性值:每个value都是对象的属性值
变量作属性名
let p1 = 'name'
let obj = { p1: 'frank' }这样写,属性名为'p1'
let obj = { [p1]: 'frank' }这样写,属性名为'name'
区别
- 不加 [] 的属性名会自动变成字符串
- 加了 [] 则会当做变量求值
- 值如何不是字符串,则会自动变成字符串
删
delete obj.xxx 或 delete obj['xxx']:即可删除obj的xxx属性;请区分[属性值为undefined] 和 [不含属性名]
查
- 查看自身所有属性:Object.keys(obj)
- 查看自身+共有属性:console.dir(obj) 或 自己依次用Object.keys 打印出 obj.proto
- 判断一个属性是自身的还是共有的:obj.hasOwnProperty('toString')
- Object.value(obj):查看所有值
- Object.entries(obj):查看所有key和value
改 增
- 基本同上:已有属性则改;没有属性则增。
- 改自身 obj['name'] = 'jack'
- 批量改自身 Object.assign(obj, {age: 18...})
let obj = {name: 'frank'} // name是字符串
obj.name = 'frank'
obj['name'] = 'frank'
obj[name] = 'frank' // 不对,因为name值不确定
obj['na'+'me'] = 'frank'
let key = 'name'; obj[key] = 'frank'
let key = 'name';
obj.key = 'frank' // 不对,因为obj.key 等价于 Obj['key']
'name' in obj和obj.hasOwnProperty('name') 的区别
前者是不管里面是否自己本身创建的,后者是会判断是否本身创建的属性
- in操作符:以下的代码name属性是原型中的,实例中没有,但是只要存在不管是原型还是实例中,都会返回true,否则返回false
- hasOwnProperty():以下代码的name属性是对象的原型,实例中没有,结果就是false
原型链
查会看原型链,增和改是不会看一个对象的原型链
原型包含了所有共有属性,共有属性依附于原型这个对象上
- JS中每一个对象都有一个隐藏属性
- 这个隐藏属性储存着其共有属性组成的对象地址
- 这个公有属性组成的对象叫做原型(共有属性)
- 也就是说,隐藏属性储存着原型(共有属性)的地址
原型
什么叫做共有属性呢?就是大家都会有这个属性叫做共有数据,但是这些属性都是再原型上
每个对象都有原型
- 原型里存着对象的共有属性
- 比如obj的原型就是一个对象
- obj._proto_存着这个对象的地址
- 这个对象里有 toString / constructor 等属性
对象的原型也是对象
- 所以对象的原型也有原型
- obj = {} 的原型即为所有对象的原型
- 这个原型包含所有对象的共有属性,是对象的根
- 这个原型也有原型,是null
修改或增加共有属性方法
- 无法通过自身修改或增加共有属性:因为他只能修改一层的属性,不能穿透两层以上的
- 我偏要修改或增加原型上的属性:obj.proto.tpString = 'xxx' // 不推荐用隐藏属性;Object.prototype.toString = 'xxx';一般来说,不要需改原型,会引出很多问题
- 不推荐使用 proto
- 推荐使用Object.create
规则就是,要改你就一开始就改,别到后面再加,可能会导致有bug
let common = { age: 18 } // 你要存在共有属性中的数据
let obj = Object.create(common)
obj.name = 'frank'