JS对象基本用法
JS对象定义
定义:无序的数据集合、键值对的集合。“键”就是key,对象的属性名;“值”就是value,对象的属性值。
属性名:每一个key都是对象的属性名(property)
属性值:每一个value都是对象的属性值。
对象的两种声明写法:
let obj = {'name' : 'tom', 'age': 18}
——'name'是一个字符串,且只能是字符串。let obj = new Object({'name': 'tom', 'age': 18})
——这是正规写法。
注意事项:
- 键名是字符串,不是标识符,但可以包含任意的字符。
- 引号可以省略,省略之后就只能写标识符了,也就是说不能以数字开头了。
- 就是算是引号省略了,键名还是字符串。
千奇百怪的属性名:
举几个例子:
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","255"]
注意事项:Object.keys(obj)——可以得到obj的所有的key。
使用变量作为属性名
写法:
let p1 = 'name'
let obj = {p1: 'tom'} //这样写属性名为'p1'
let obj = {[p1]: 'tom'} //这样写,属性名为'name'
对比上面两种写法:
- 不加[]的属性会自动变成字符串,加了[]的会当作变量求值,如果值不是字符串,则会自动变成字符串。
对象的隐藏属性
关于隐藏属性的理解:
- JS中没有个对象都有一个隐藏属性,
- 这个隐藏属性储存着其共有属性组成的对象的地址
- 这个共有属性组成的对象就是原型
- 所以,隐藏属性存着原型的地址。 举例说明:
let obj = {'name': 'Tom','age': 18}
let obj2 = {'name': 'June','age': 20}
obj.toString === obj2.toString
<= true
对于obj和obj2来说,它们又自己独有的自身的属性,同时也有共有的属性——toString,而toString等共有属性所组成的对象就是原型。内存图如下:
关于原型
每一个对象都有原型
- 原型里存着对象的共有属性
- obj的原型就是一个对象
obj__proto__
存着这个对象的地址- 对象里面有toString/constructor/valueOf等属性
对象的原型也是对象
- 因为一个对象的原型是对象,这个对象也有原型,所以一个对象的原型也有原型。
obj={}
的原型即为所有对象的原型。- 这个原型包含了所有对象的共有属性,是对象的根。
- 这个原型的原型是null。
如何删除对象的属性
方法一:使用delete删除属性名和值
delete obj.xxx或者delete obj['xxx']。即可删除xxx属性的名和值
方法二:只删除属性的值,但会保留名
obj.xxx = undefined。即可删除xxx属性的值,但是会保留名。
注意:obj.xxx === undefined,不能断定'xxx'是否为obj的属性。例如:
let obj{}
let obj{xxx : undefined}
<-
obj.xxx === undefined
<- true
obj2.xxx === undefined
<- true
所有无法使用obj.xxx === undefined来判断属性名,只能判断值。
如何查看对象的属性(读属性)——会看到原型链
查看自身属性
Object.keys(obj)
——> 属性名(key)Object.values(obj)
——> 值(value)Object.entries(obj)
——> 属性名和值(key+value)
查看是否含属性名
通过使用in来判断
'xxx' in obj === false
——> 不含'xxx' in obj ==== true
——> 含
查看自身和共有属性
- 通过目录的形式打印出来:
console.dir(obj)
- 或者自己依次使用
Object.keys
打出obj.__proto__
,但是不推荐。
判断一个属性是自身还是共有的
使用obj.hasOwnProperty('toString')
来判断。与'xxx' in obj
查看是否有这个属性,但是不确定自身还是共有的进行配合使用。
查看单个属性
有三个方法:
- 中括号语法:
obj['key']
- 点语法:
obj.key
- 坑新人的语法:
obj[key] // 变量key的值一般不为'key'
注意:新人请优先选择中括号语法。
举例:
boj.name
等价于obj['name']
,其中name是字符串;不等价于obj[name]
这个其中的name为变量。
let name = 'tom'
obj[name] === obj['name']
let list = ['name','age','gender']
let person = {
name : 'tom',age : 18, gender : 'man'
}
for(let i = 0; i<list.length; i++){
let name list[i]
console.log(person????)
}
请问在???处填上一下哪个可以使得person的所有属性被打印出来
选项:
console.log(person.name)
console.log(person[name])
答案是:2。因为第一个选项只能的name是字符串,打印了三次都是打印出name的值。第二个选项中的name是个变量,在打印三次中,一次打印出了name,age,gender。所以选择2。由此可见:区分name和'name'真的很重要。
如何修改或增加对象的属性(写属性)——不会修改到原型链
直接赋值
举例:
let obj = {name:'tom'}
——name为字符串obj.name = 'tom'
——name为字符串obj['name'] = 'tom'
——name为字符串——这个是错误写法,因为name是一个变量,值不确定。obj[name] = 'tom'
obj['na' + 'me'] = ''tom
——先运算为一个字符串'name'再赋值let key = 'name'; obj[key] = 'tom'
——先声明一个变量,再使用这个变量赋值——这个是错误的写法,因为let key = 'name'; obj.key = 'tom'
obj.key
等价于obj['key']
批量赋值
使用Object.assign(obj,{age:18,gender:'man'})
。可以做到批量赋值。
修改或增加共有属性
因为无法通过自身修改或增加共有属性。例如:
let obj ={}, obj2 = {} //共有toString
obj.toString='xxx' //只会修改在obj的自身属性上
obj.toString //还是在原型上
如果一定修改或增加共有属性,可以使用两种方法:
obj.__proto__.toString = 'xxx'
——不推荐使用__proto__window.Object.prototype.toString = 'xxx'
——一般不要修改原型,会出现很多问题
修改或删除原型(修改隐藏属性)
- 删除原型:
obj__proto__ = null
- 修改原型: 方法一:不推荐——proto,因为会导致性能很低
let obj = {name:'tom'}
let obj2 ={name:'jack'}
let common = {kind:'human'}
obj.__proto__ = common
obj2.__proto__ = common
内存图——原型链
方法二:推荐使用Object.create
let obj =Object.create(common)
obj.name = 'tom'
let obj2 = Object.create(common)
obj.name = 'jack'
总结:如果要改原型,就一定要在一开始就改,再去添加属性。
'name' in obj
和obj.hasOwnProperty('name')
的区别
其区别在于
obj.hasOwnProperty('name')
可以判断出一个属性是否是自身属性。- 再通过
'name' in obj
只是查看对象中是否有这个属性,来确定是自身属性还是共有属性。