构造函数
- 构造函数主要作用是用于实例化类,类实例是由构造函数构造的,构造函数的主要任务是初始化实例需要的信息。(通常构造函数的首字母一般大写)。
- 构造函数使用
new
关键字调用实现实例化类主要是1
2
3
4
5
6
7function Animal () {
this.type = 'animal'
}
let dog = new Animal()
let cat = new Animal()
dog.type // animal
cat.type // animalnew
的作用,new
的主要作用如下:- 自动创建一个空对象
- 为新创建的对象添加proto,将该属性链接至构造函数的原型对象
- 把空对象和函数里的this 衔接起来(this指向实例化对象)
- 隐式返还
this
(即该函数没有返回对象,则返回this
);
在例子中 ,一个继承自Animal.prototyper的新对象被创建,this
会指向dog。所以在调用时Animal里的this
会指向dog,因此调用dog.type,会打印’animal’- 基于
new
的作用,可以仿写一个new运算符1
2
3
4
5
6
7
8
9
10
11
12
13function mynew(constructor, ...arg) {
//创建 一个空对象
let obj = {}
// this指向obj对象
constructor.call(obj, ...arg)
// 添加属性__proto__,指向构造函数的原型
obj.__proto__ = constructor.prototype;
// 返回 对象
return obj
}
// 使用
let dog = mynew(Animal)
dog.type // animal构造函数的原型链
因为new
会为新的对象添加proto,并将该属性链接至构造函数的原型对象,所以原型链如下所示:
- 基于
其中Animal.prototype会有一个默认的constructor属性,引用对象关联的函数(在本例中是Animal)。
1 | Animal.prototype.constructor === Animal // true |
需要注意的是dog.constructor之所以会“指向创建dog的函数Animal”是因为dog本身并没有constructor属性,访问它时会委托到Animal.prototype,而Animal.prototype.constructor默认指向Foo。
也正因为构造函数有这样的原型链,所以可以用来实现工厂模式。 一个简单的实现如下:
1 | function Animal (name) { |
访问dog的myName方法,因为本身没有这个方法,会通过原型链访问到Animal.prototype上。因此我们可以在Animal.prototype上定义共有的方法来封装。
继承
构造函数其实也是一种继承,是类和实例之间的继承,dog可以”继承”Animal.prototype并访问到Animal.prototype的MyName函数。而我们更多使用的是类和类之间的继承。
类和类之间的继承主要使用的是Object.create()函数
,它会创建一个新对象并把新对象的proto关联到你指定的对象。在下面的例子中就是创建一个新的Son.prototype对象并关联到Dad.prototype。(会抛弃默认的Son.prototype)
1 | function Dad (name) { |
ES6 可以使用Object.setPrototypeOf
直接修改现有的Bar.prototype, 此时Son.prototype.constructor不需要修复
1 | Objcet.setPrototypeOf(Son.prototype, Dad.prototype) |
小结
这是最近在重新学习JS相关知识时,所整理的有关构造函数的部分,觉得有所帮助就点个赞和收藏^_^。