声明对象
1. 声明对象的两种语法
第一种写法:
let obj = {
'name' : 'meng',
'age' : 18
}
第一种写法:
let obj = new Object({
'name' : 'meng',
'age' : '18'
})
两种语法都可以用,第一种相对于第二种简单一些,所以第一种用的多
- 注意
- 对象都是以键值对的形式出现
- 键名是字符串,不是标识符,可以包含任意字符串
- 引号可以省略,省略之后只能按标识符的规则写(数字除外)
- 就算引号省略了,键名也还是字符串
- 当键名有空格,中文等特殊符号是,必须加引号,否则会出错
- 没有数字键名,也没有数字下标,因为浏览器会自动把数字转换成字符串
2. 属性名(keys)
- 每个 key 都是对象的属性名(property)
除了上述介绍的键名命名规则,这里还有几个有奇怪 的属性名
let obj = {
1: 'a',
3.2: 'b',
1e2: true,
1e-2: true,
.234: true,
0xFF: true
}
在浏览器上打印出 obj 的属性名,结果如下
不难看出只有 1 和 3.2 没有变化
其他的键名都被浏览器进行了运算
所以建议在有特殊字符,或者有非英文的键名上不要省略引号
3. 变量作属性名
let p1 = 'name'
let obj = {p1: 'frank'} // 这样写,属性名为 'p1'
let obj2 = {[p1]: 'frank'} // 这样写,属性名为 'name'
复制代码
-
对比
- 不加 [] 的属性会自动变成字符串
- 加了 [] 的属性会当做变量求值
- 值如果不是字符串,则会自动变成字符串
4. 对象的隐藏属性
代码示例
let obj = {}
obj.toString() // 不报错
// 因为 obj 的隐藏属性对应的对象上有 toString()
复制代码
这种隐藏属性叫做对象的原型
原型要注意以下几点:
-
每个对象都有原型
-
对象的原型也是对象
- 所以对象的原型也有原型
- obj = {} 的原型即为所有对象的原型
- 这个原型包含所有对象的共有属性,也就是对象的根
- 这个原型也有原型,是 null
可能会有点绕,我用代码解释一下
对象的增删改查
1. 如何删除对象的属性
let obj = {
name: 'meng',
age: '18',
gender: 'man'
}
obj.name = undefined // 把 name 属性设置为 undefined
delete obj.name // 删除属性
上述代码请区分属性值为 undefined 和 不含属性名
-
不含属性名
- 可以用下面代码验证对象是否含有此属性
'name’ in obj === false
-
含有属性名,但是值为 undefined
- 可以用下面代码验证含有属性且属性的值为 undefined
'name' in obj && obj.name === undefined
// obj.name === undefined 不能判断 name 是否为 obj 的属性,所以要做一个 && 运算
注意:把属性设置为 undefined 不是删除此属性,只是改变了属性的值,这个要和 delete 区分开
2. 如何查看对象的属性
查看所有属性
- 查看自身所有属性
let obj = {
name: 'meng',
age: 18
}
Object.keys(obj) // 查看所有键
Object.values(obj) // 查看所有值
Object.entries(obj) // 查看键和值
- 查看自身和共有属性
console.dir(obj)
Object.keys(obj.__proto__) // 不推荐用这种方法
- 判断一个属性是自身还是共有的
obj.hasOwnProperty('toString')
如果返回值为 false,那么这个属性就不是自身的属性
反之,返回 true 的话这个属性就是自身的属性
查看单个属性
- 中括号语法
obj['key']
- 点语法
obj.key
- 上两种方法的变体
let key = ‘xxx’
obj[key] // key 为变量
新手建议使用第一种方法,明确且不会入坑
3 & 4. 如何修改或增加对象的属性
- 直接赋值
let obj = {
'name': 'frank'
}
obj.name = 'meng' // 修改属性
obj.age = 13 // 增加属性
// 如果对象有此属性就为修改,没有此属性就为增加
这是一个一个赋值,有时候可能会很麻烦,新版的 ES6 就提供了一个 API 用于添加多个属性
- 批量赋值
let obj = {}
Object.assign( obj, {'name':'meng', 'age': '18'})
- 使用 proto 修改
var common = { '国籍':'中国',hairColor:'black'}
var person = {jj: '11'}
person.__proto__ = common // 把原型的地址改成 common 的地址
复制代码
💥2. 使用 ES6 新的 API 来修改原型
var common = { '国籍':'中国',hairColor:'black'}
var person = Object.create(common)
let obj = Object.create(common)
obj.name = 'frank'
let obj2 = Object.create(common)
obj2.name = 'jack'
推荐使用第二种 ES6 新 API,因为第一种会有性能问题
无法通过自身修改或增加自有属性
let obj = {}
let obj2 = {} //obj和obj2共有toString
obj.toString = 'xxx' //只会修改Obj自身属性,obj2.toString还在原型上
偏要修改或增加原型上的属性
obj.__proto__.toString = 'xxx' //比推荐使用__proto__
Object.prototype.toString = 'xxx'
-- 一般来说,不推荐修改原型,会引起很多问题
总结一句话,所有 "proto" 代码都是强烈不推荐写的
5. 'name' in obj和obj.hasOwnProperty('name') 的区别
都是两种查看属性是不是在对象里的方法
前者自身属性和共有属性都返回true,后者仅仅是自身属性才返回true