JS红宝书-第八章-对象

本章总结了JS中对象的内容

JS的对象定义为一组属性的无序集合,类似于一个散列表,内容是k/v对,v是值或函数。

定义对象的两种方式

1
2
3
4
5
let person = new Object()
person.name = "jojo"
person.sayName = function () {
console.log(this.name)
}
1
2
3
4
5
6
let person = {
name:"jojo",
sayName() {
console.log(this.name)
}
}

属性类型

1 数据属性

属性如下:

  • configurable 是否可以使用delete、修改特性、修改为访问器属性等
  • enumberable 是否可以通过for in语句进行便利
  • writable 属性值是否可以被修改
  • value 包含实际属性的值
1
2
3
4
5
6
7
let obj = {}
Object.defineProperty(obj, "info", {
writable: false,
value: 'haha'
})
obj.info = 'jaja'
console.log(obj.info) // haha

2 访问器属性

属性如下:

  • configurable 是否可以使用delete、修改特性、修改为访问器属性等
  • enumberable 是否可以通过for in语句进行便利
  • get 属性值是否可以被修改
  • set 包含实际属性的值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
let obj = {
}

Object.defineProperty(obj, "cnt_", {
writable : true, //注意这里默认是false
value:0
})

for(let i in obj) console.log(i)
Object.defineProperty(obj, "cnt", {
get() {
this.cnt_ += 1
return this.cnt_
},
set(val) {this.cnt_ = val}
})
console.log(obj.cnt)
console.log(obj.cnt)
obj.cnt = 100
console.log(obj.cnt)
console.log(obj.cnt)

读取属性

按key读取:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
let obj = {
}

Object.defineProperty(obj, "cnt_", {
writable : true, //注意这里默认是false
value:0
})

for(let i in obj) console.log(i)
Object.defineProperty(obj, "cnt", {
get() {
this.cnt_ += 1
return this.cnt_
},
set(val) {this.cnt_ = val}
})

console.log(Object.getOwnPropertyDescriptor(obj,"cnt"))
//{enumerable: false, configurable: false, get: ƒ, set: ƒ}

全部读取:使用getOwnPropertyDescriptors方法,会返回一个新的静态对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
let obj = {
}

Object.defineProperty(obj, "cnt_", {
writable : true, //注意这里默认是false
value:0
})

for(let i in obj) console.log(i)
Object.defineProperty(obj, "cnt", {
get() {
this.cnt_ += 1
return this.cnt_
},
set(val) {this.cnt_ = val}
})

console.log(Object.getOwnPropertyDescriptors(obj))
//cnt: {enumerable: false, configurable: false, get: ƒ, set: ƒ}
//cnt_: {value: 0, writable: true, enumerable: false, configurable: false}

合并对象

注意 合并对象操作Object.assign是浅拷贝

1
2
3
dest = {}
Object.assign(dest, {test:1}, {test1:2})
console.log(dest)

创建对象

1.工厂模式

1
2
3
4
5
6
7
8
function createPerson(age) {
let obj = new Object()
obj.age = age
obj.sayAge = function () {
console.log(this.age)
}
return obj
}

缺点:

  • 无法显示识别类别

2.构造函数模式

1
2
3
4
5
6
7
8
9
10
11
function Person(age) {
this.age = age
this.sayAge = function(){
console.log(this.age)
}
}
let p1 = Person(1)
let p2 = Person(2)
console.log(p1.constructor === Person)
console.log(p1 instanceof Person)
console.log(p1 instanceof Object)

优点:

  • 可以进行类型判断
    步骤:
  • 内存中创建了新对象
  • 分配prototype
  • 分配this
  • 执行构造器中内部代码
  • 返回非空,则返回该对象,如果没有返回对象 则返回this

2.1 构造函数是函数

1
2
3
4
5
6
7
8
9
let o = new Object()
function Person(age) {
this.age = age
this.sayAge = function(){
console.log(this.age)
}
}
Person.call(o,1)
console.log(o.age)

2.2 构造函数的问题

  • function的相等问题
1
2
3
4
5
function Test() {
this.test = function () {}
}

console.log((new Test()).test === (new Test()).test) // false

3.原型模式

只要创建一个函数,就会按照特定规则创建一个prototype对象
虽然JS中没有标准的访问prototype的方式,但是在Chrome和Firefox等实现中可以根据__proto__属性进行访问

1
2
3
4
5
6
7
function Person(){}
Person.prototype.age = 123
Person.prototype.sayAge = function () {console.log(this.age)}
let x = new Person()
x.sayAge() // 123
console.log(x.__proto__.constructor === Object) // true
Object.getPrototypeOf(x)

实例与构造函数之间没有直接联系,但是与构造函数原型之间有直接联系。

3.1. 原型层级

1
2
3
4
5
6
7
8
9
function Person() {}
Person.prototype.age = 128
let p1 = new Person()
let p2 = new Person()
p2.age = 111
console.log(p1.age)//128
console.log(p2.age)//111
delete p2.age
console.log(p2.age)//128

为什么会发生这种现象?因为对p2对象的修改使其修改了age属性,遮蔽了原型链上的age属性,经过遮蔽后,删除该属性,即可恢复链接

3.2.in操作符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function Person() {}
Person.prototype.age = 128
let p1 = new Person()
let p2 = new Person()
p2.age = 111
console.log(p1.age)//128
console.log(p1.hasOwnProperty('age'))//false
console.log('age' in p1)//true
console.log(p2.age)//111
console.log(p2.hasOwnProperty('age'))//true
delete p2.age
console.log(p2.age)//128
console.log(p2.hasOwnProperty('age'))//false
console.log(Object.keys(Object.getPrototypeOf(p2))) // ['age']
console.log(Object.keys(p2)) // []

面试题

for in 和 for of 区别

for in 遍历出原型的属性怎么办(用hasOwnProperty检测)

数据类型判断

基本数据类型
判断数据的类型,typeof的局限, 如何解决这个局限
instanceof 原理
原型链的理解
new 原理
await使用什么实现(生成器, yield star)
Promise / sleep
bigint int


JS红宝书-第八章-对象
https://tech.jasonczc.cn/2022/language/javascript/redbook/8-object/
作者
CZY
发布于
2022年4月29日
许可协议