声明对象
JavaScript的对象是一种无序的集合数据类型,它由若干键值对组成。
写法
let obj = { 'name': 'frank', 'age': 18 }
let obj = new Object({'name': 'frank'})
上面代码中,键名是字符串,不是标识符,可以包含任何字符串
可以省略掉引号,省略后就只能写标识符
let obj = { name: 'frank', 'age': 18 }
// name 依旧是字符串
但是,就算是省略了引号,键名也还是字符串
属性名和属性值
每一个 key 都是对象的属性名(property)
每一个 value 都是对象的属性值
奇怪的属性名
所有属性名都会自动变成字符串
let obj = {
1 : 'a',
3.2 : 'b',
1e2 : 'c',
1e-2 : 'd',
.234 : 'e',
0xFF : 'f'
}
Object.keys(obj) //得到对象所有的 key
//结果为:['1', '100', '255', '3.2', '0.01', '0.234']
上面代码中的属性名发生了变化,JS会先运算出结果,再将结果变成字符串作为属性名
另外 Object.keys() 可以得到对象所有的 key
对象作为属性名
let a = 'name'
let obj = { a : 'frank'} //属性名为 'a'
let obj2 = { [a] : 'frank'} //属性名为变量 a
//结果: obj{a:'frank'} ; obj{name:'frank'}
上面代码中,不加 [] 的属性名会自动变成字符串,加上 [] 则会当做变量求值
变量的值如果不是字符串,则会自动变成字符串
对象中的隐藏属性
JS 中每一个对象都有一个隐藏属性
这个隐藏属性中储存着其共同属性组成的对象地址
这个共同属性组成的对象叫做原型,就是说隐藏属性储存着原型的地址
例子:
//声明 2 个对象
let obj = { name : 'frank' , age : 18}
let obj2 = { name : 'jack' , age : 20}
内存图:
let obj = { name : 'frank' , age : 18}
obj.toString()
不会报错,因为 obj 的隐藏属性对应的对象上有 toString()
上图中, #409 为原型,原型其实也是一个对象 ,是对象就会有隐藏属性,#409 原型的隐藏属性指向的原型为 null ,也就是说 #409 原型就是对象的根。
测试:
let obj = { name : 'frank' , age : 18}
obj.__proto__.__proto__
//结果:null
上面代码中, null 并不代表 __proto__ 不存在,而是它的值为 null
增删查改
属性删除
删除对象中的属性
delete obj.xxx
//或者
delete obj['xxx']
undefined
let obj = { name : 'frank' , age : 18}
obj.name = undefined
// 结果:[name : undefined ,age : 18]
let obj = { name : 'frank' , age : 18}
delete obj.name
// 结果:[age : 18]
上面代码中,将属性值赋值为 undefined 并不能将属性删除
判断是否删除
let obj = { name : 'frank' , age : 18}
delete obj.name
'name' in obj
//结果: false,说明 name 不在 obj 对象中
上面代码中, in 判断属性是否在对象中
注意 obj.xxx === undefined 不能判断 xxx 是否为 obj 的属性
例子:
let obj = { name : undefined}
let obj2 = {}
obj.name === undefined
// 结果:true
obj2.name === undefined
// 结果:true
属性查找
查看所有属性
let obj = { name : 'frank' , age : 18}
Object.keys(obj)
// 查看自身所有 key
Object.values(obj)
// 查看自身所有属性值
上面代码中,查看自身所有 key 和 value
let obj = { name : 'frank' , age : 18}
console.dir(obj)
上面代码可以查看自身 + 共用属性
判断属性是自身还是共有
let obj = { name : 'frank' , age : 18}
obj.hasOwnProperty('toString')
// 结果:false
上面代码中, hasOwnProperty 判断是否为自身属性, toString 为共有属性,所有为 false
in 与 hasOwnProperty 的区别
let obj = { name : 'frank' , age : 18}
'toString' in obj
// 结果: true ,toString 在 obj 中
obj.hasOwnProperty('toString')
// 结果: false , toString 不是 obj 自身属性
上面代码中, in 无法判断属性是否为自身还是共有属性, hasOwnProperty 可以
查找单个属性
let obj = { name : 'frank' , age : 18}
obj['name']
//或者
obj.name
obj[name] //错误写法
// 结果: undefined
上面代码中,可以通过 key 来查找单个属性,但是 obj[name] 中的 name 会被当做变量,而不是 key
obj.name
// 等于
obj['name']
// 不等于
obj[name]
这里的 name 应该是一个字符串,而不是变量
let name = 'jack'
obj[name]
// 等于
obj['jack']
属性增和改
属性增加跟改一样,有属性则改,没属性则增
直接赋值
let obj = {name: 'frank'}
obj.name = 'jack'
// 或者
obj['name'] = 'jack'
// 或者
obj['na'+'me'] = 'jack'
// 或者
let key = 'name'
obj[key] = 'jack'
错误写法:
let obj = {name: 'frank'}
obj[name] = 'jack'
//错误,name 为变量,值不确定
let key = 'name'
obj.key = 'jack'
//错误, obj.key 等于 obj['key']
批量赋值
let obj = {name: 'frank'}
Object.assign(obj,{name: 'jack',age: 18,gender: 'man'})
上面代码中, assign 可以进行批量增加或修改,有属性则改,没属性则增
增加或修改 原型属性
let obj = {} , obj2 = {}
obj.toString = 'xxx' // 修改 toString
obj2.toString //obj2 还在原型上
上面代码说明,我们无法直接修改原型的属性,在读取时会走原型,但是在写入时就不会走原型
如何修改原型属性
let obj = {} , obj2 = {}
obj.__proto__.toString = 'xxx' //修改原型 toString
obj2.toString // toString 变成了 'xxx'
上面代码中,我们可以利用 obj.__proto__.toString 修改原型属性,但不推荐使用 __proto__
另一种方法:
let obj = {} , obj2 = {}
//obj 对象原型等于 Object.prototype
//测试
obj.__proto__.toString === Object.prototype.toString
//结果:true , 说明两者相等
Object.prototype.toString = 'xxx' //修改原型属性
obj.toString
obj2.toString
// 两个都是 'xxx'
上面代码中,发现 obj.__proto__.toString 等于 Object.prototype.toString ,说明是同一原型,所以我们可以直接修改,但一般来说,不要修改原型,会引起很多问题。
修改隐藏属性
let obj = {name : 'frank'}
let obj2 = {name : 'jack'}
obj.__proto__ = obj2 //修改隐藏属性 __proto__
obj //查看 obj 对象
obj.toString //依旧可以调用
上面代码中,我们修改了 obj 的隐藏属性, obj 中隐藏属性中有 obj2 的属性,toString 依旧可以调用,因为 obj2 中也有 __proto__ 可以指向原型,所有 obj 依旧可以调用 toString ,这种称之为原型链。
依旧不推荐使用 __proto__
另一种方法:
let obj2 = {name : 'jack'}
let obj = Object.create(obj2) //指定 obj2 为原型
obj.name = 'frank' //obj 里面添加属性
obj // 查看 obj 对象
上面代码中,通过 create 方法,在创建 obj 对象时就指定了 obj2 为原型,要改就一开始就改,别后来再改