JavaScript-引用类型
对象数据类型即引用类型
mindmap 对象数据类型 普通对象 类数组 实例 原型对象 数组对象 正则对象 日期对象 Set/Map
创建对象
创建字面量(Literal)对象
由 0 到 多组键值对(属性名和属性值)组成。
- 属性名是对象的一个属性;
- 属性名一般是字符串,也可以是数字、布尔值、undefined、null、Symbol
Uncaught SyntaxError: Unexpected number 属性名不可以是 bigInt 类型 - 如果将属性名设置为 Object 类型,会通过 toString 将属性名转换为 [object Object]
- 属性名设置为函数,可以正常编译通过。
1 | let symb = Symbol('bracket') |
创建实例对象
1 | let baby = new Object() |
开发过程中实际多采用字面量形式创建对象,字面量对象避端是产生大量重复代码**
对象成员访问
获取对象中某个属性名对应的属性值
- 对象.属性名
仅适用于属性名为字符串类型 - 对象[属性名]
注意:这种方式获取属性值时,要特别关注属性名数据类型
1 | console.log(myBaby.name) // Audery |
对象内置属性__proto__
[[prototype]] 对象属性,对象创建时生成
原型和原型链
JavaScript 是基于原型的面向对象语言,对象默认有 prototype,可以将需要共享的实例方法绑在 prototype 上,达到方法共享的目的。对象每个实例都有各自 __proto__
属性,该属性指向对象的 prototype 属性上。这种原型链接的关系称为原型链,null 是原型链的最后一个链接。
JavaScript 继承
- 原型链继承
1
2
3
4function Super() {}
function Son() {}
// 实现继承
Son.prototype = new Super()只要把子类的原型指向父类的实例就可以了,再演示一个更丰满的例子
1 | function Base() { |
引用类型会出现数组引用多实例因共享导致的相互污染的问题,考虑使用 ** 构造函数继承 ** 实现
构造函数继承
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16function Base(female) {
this.sex = female
this.friends = ['lily', 'lucy', 'coco']
}
function Son(name, age, female) {
// 对象冒充调用父类方法
Base.call(this, female); // 子类冒充父类,子类调用父类构造函数。即,子类复制子父类代码
this.name = name;
this.age = age
}
let Audery = new Son('Audery', 2)
let Gulu = new Son('Gulu', 2)
Gulu.friends.push('emily')
console.log(Audery.friends)
console.log(Gulu.friends)上面说了,通过对象冒充调用父类构造方法,其实就是复制父类构造函数中的属性、方法,到子类构造函数中,原型方法无法继承
组合继承
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23function Base(female) {
this.sex = female
this.friends = ['lily', 'lucy', 'coco']
}
Base.prototype.say = function() {
return 'I have some friends, they are ' + this.friends.join('、')+' respectively!'
}
function Son(name, age, female) {
// 对象冒充调用父类方法
Base.call(this, female); // 子类冒充父类,子类调用父类构造函数。即,子类复制子父类代码
this.name = name;
this.age = age
}
// 原型继承父类实例指向子类原型
Son.prototype = new Base()
let Audery = new Son('Audery', 2)
let Gulu = new Son('Gulu', 2)
Gulu.friends.push('emily')组合继承实现了:
- 属性私有化、方法共享、引用数组间不相互污染
** 以上是原型链继承的周边,不使用 Object.create, 以下是使用 Object.create 方法相关继承的演生 **
原型式继承
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17function base(o) {
function F(){}
F.prototype = o;
return new F();
}
var baseObj = {
name: '基类',
arr: ['array1','array2','array3'],
fn: function() {
console.log(this.name, this.arr)
}
}
var baseInstance1 = base(baseObj)
var baseInstance2 = base(baseObj)
baseInstance2.name = '修改属性值'
baseInstance1.arr.push('array4')
/* === baseInstance2 添加了一个实例属性 === */寄生式继承
寄生组合继承
Class extends
如果子类中存在构造函数,则需要在使用 this 之前首先调用 super。 与寄生组合继承不同的是,ES6 先将父类实例对象的属性和方法加到 this 上,必须先调用 super 方法,然后再用的子类构造函数修改 this
1 | /** |
实现原理
1 | class A {} |