《JS对象基本用法》

278 阅读4分钟

JS对象基本用法

JS对象定义

定义:无序的数据集合、键值对的集合。“键”就是key,对象的属性名;“值”就是value,对象的属性值。

属性名:每一个key都是对象的属性名(property)

属性值:每一个value都是对象的属性值。

对象的两种声明写法:

  1. let obj = {'name' : 'tom', 'age': 18}——'name'是一个字符串,且只能是字符串。
  2. let obj = new Object({'name': 'tom', 'age': 18})——这是正规写法。

注意事项:

  1. 键名是字符串,不是标识符,但可以包含任意的字符。
  2. 引号可以省略,省略之后就只能写标识符了,也就是说不能以数字开头了。
  3. 就是算是引号省略了,键名还是字符串

千奇百怪的属性名:

举几个例子:

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'

对比上面两种写法:

  1. 不加[]的属性会自动变成字符串,加了[]的会当作变量求值,如果值不是字符串,则会自动变成字符串。

对象的隐藏属性

关于隐藏属性的理解:

  1. JS中没有个对象都有一个隐藏属性,
  2. 这个隐藏属性储存着其共有属性组成的对象的地址
  3. 这个共有属性组成的对象就是原型
  4. 所以,隐藏属性存着原型的地址。 举例说明:
let obj = {'name': 'Tom','age': 18}
let obj2 = {'name': 'June','age': 20}
obj.toString === obj2.toString
<= true

对于obj和obj2来说,它们又自己独有的自身的属性,同时也有共有的属性——toString,而toString等共有属性所组成的对象就是原型。内存图如下:

内存图1.PNG

关于原型

每一个对象都有原型

  1. 原型里存着对象的共有属性
  2. obj的原型就是一个对象
  3. obj__proto__存着这个对象的地址
  4. 对象里面有toString/constructor/valueOf等属性

对象的原型也是对象

  1. 因为一个对象的原型是对象,这个对象也有原型,所以一个对象的原型也有原型。
  2. obj={}的原型即为所有对象的原型。
  3. 这个原型包含了所有对象的共有属性,是对象的根
  4. 这个原型的原型是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来判断属性名,只能判断值。

如何查看对象的属性(读属性)——会看到原型链

查看自身属性

  1. Object.keys(obj)——> 属性名(key)
  2. Object.values(obj)——> 值(value)
  3. Object.entries(obj)——> 属性名和值(key+value)

查看是否含属性名

通过使用in来判断

  1. 'xxx' in obj === false——> 不含
  2. 'xxx' in obj ==== true——> 含

查看自身和共有属性

  1. 通过目录的形式打印出来:console.dir(obj)
  2. 或者自己依次使用Object.keys打出obj.__proto__,但是不推荐。

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

使用obj.hasOwnProperty('toString')来判断。与'xxx' in obj查看是否有这个属性,但是不确定自身还是共有的进行配合使用。

查看单个属性

有三个方法:

  1. 中括号语法:obj['key']
  2. 点语法:obj.key
  3. 坑新人的语法:obj[key] // 变量key的值一般不为'key'

注意:新人请优先选择中括号语法。

举例:

  1. 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的所有属性被打印出来

选项:

  1. console.log(person.name)
  2. console.log(person[name]) 答案是:2。因为第一个选项只能的name是字符串,打印了三次都是打印出name的值。第二个选项中的name是个变量,在打印三次中,一次打印出了name,age,gender。所以选择2。由此可见:区分name和'name'真的很重要。

如何修改或增加对象的属性(写属性)——不会修改到原型链

直接赋值

举例:

  1. let obj = {name:'tom'}——name为字符串
  2. obj.name = 'tom'——name为字符串
  3. obj['name'] = 'tom'——name为字符串
  4. obj[name] = 'tom'——这个是错误写法,因为name是一个变量,值不确定。
  5. obj['na' + 'me'] = ''tom——先运算为一个字符串'name'再赋值
  6. let key = 'name'; obj[key] = 'tom'——先声明一个变量,再使用这个变量赋值
  7. 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  //还是在原型上

如果一定修改或增加共有属性,可以使用两种方法:

  1. obj.__proto__.toString = 'xxx' ——不推荐使用__proto__
  2. window.Object.prototype.toString = 'xxx'——一般不要修改原型,会出现很多问题

修改或删除原型(修改隐藏属性)

  1. 删除原型:obj__proto__ = null
  2. 修改原型: 方法一:不推荐——proto,因为会导致性能很低
let obj = {name:'tom'}
let obj2 ={name:'jack'}
let common = {kind:'human'}
obj.__proto__ = common
obj2.__proto__ = common

内存图——原型链

内存图2.PNG

方法二:推荐使用Object.create

let obj =Object.create(common)
obj.name = 'tom'
let obj2 = Object.create(common)
obj.name = 'jack'

总结:如果要改原型,就一定要在一开始就改,再去添加属性。

'name' in objobj.hasOwnProperty('name')的区别

其区别在于

  1. obj.hasOwnProperty('name')可以判断出一个属性是否是自身属性。
  2. 再通过'name' in obj只是查看对象中是否有这个属性,来确定是自身属性还是共有属性。