构造函数的书写
在 ES6 之前,类的创立是利用构造函数来进行的。
上面的代码就是一个构造函数的书写,咱们习惯将构造函数的首字母进行大写:
function Person(name, age) {
this.name = name
this.age = age
}
Person.prototype.running = function() {console.log(this.name + "running~")
}
const person = new Person('lisa', 18)
person.running() // lisa running~
在这个代码当中,办法没有被间接书写在构造函数“当中”,而是写在原型当中。这是因为咱们在创立实例对象的时候,会对其中的属性和办法调配存储空间,然而办法是一样的,如果每次创立实例对象都给办法调配空间就会有点节约,然而写在原型当中就不会存在这个状况,当实例对象调用办法的时候,他会去到原型当中寻找到该办法,那个办法从始至终都只有那“一个”。
多个构造函数的属性和办法重叠
有时候咱们书写构造函数时,会发现它们存在雷同的属性或者办法,就像上面的两个构造函数一样:
Teacher 类:
function Teacher(name, age, title) {
this.name = name
this.age = age
this.title = title
}
Teacher.prototype.eatting = function() {console.log(this.name + "eatting~")
}
Teacher.prototype.teaching = function() {console.log(this.name + "tearching~")
}
Student 类:
function Student(name, age, sno) {
this.name = name
this.age = age
this.sno = sno
}
Student.prototype.eatting = function() {console.log(this.name + "eatting~")
}
Student.prototype.studying = function() {console.log(this.name + "studying~")
}
咱们能够发现 Teacher 类和 Student 类当中的 name、age 属性以及 eatting 呈现了重叠,这个时候就能够利用面向对象当中的封装与继承思维了,将雷同的属性和办法封装成一个父类,再让 Teacher 类和 Student 继承于它。
在 ES6 之前是不存在 extends 这个继承关键字,下来就说一下基于原型链的继承办法。
(1)利用构造函数
function Person(name, age) {
this.name = name
this.age = age
}
Person.prototype.eatting = function() {console.log(this.name +"eatting~")
}
// 子类
function Student(name, age, sno) {Person.call(this, name, age)
this.sno = sno
}
Student.prototype = new Person()
Student.prototype.studying = function() {console.log(this.name + "studying~")
}
const stu = new Student('lisa', 18, 111)
stu.eatting()
stu.studying()
很显然,在这种办法当中,咱们调用了两次父类的构造函数。
(2)原型式继承
这种想法能够用上面图来进行展现:
Teacher 类和 Student 类两个构造函数的原型都指向各自的两头原型,而两头原型最终指向了 Person 类。
依据这个想法,咱们能够写一个用于继承的函数:
function inherit(obj) {function middleFn() {}
middleFn.prototype = new obj()
return new middleFn()}
function Person(name, age) {
this.name = name
this.age = age
}
Person.prototype.running = function() {console.log(this.name + "running~")
}
function Student(sno) {this.sno = sno}
Student.prototype = inherit(Person)
Student.prototype.studying = function() {console.log(this.name + "studying~")
}
const stu = new Student('lisa', 18, 1111)
stu.running() // lisa running~
stu.studying() // lis studying~
在这个函数当中,咱们设计了一个两头构造函数,它的原型指向了传进来的构造函数,这个继承函数最初返回了两头构造函数的实例对象。
这个时候咱们就只须要将 Student 构造函数的原型指向返回的实例对象就能够实现图中的模式。
这个 inherit 函数还能够利用 Object 当中的 setPrototypeOf 进行书写,也就是上面的办法:
function inherit2(obj) {const newObj = {}
Object.setPrototypeOf(newObj, obj)
return newObj
}
const obj = {name: 'peter'}
const obj2 = inherit2(obj)
console.log(obj2.name) // peter
亦或者是利用 Object.create() 办法:
function inherit3(obj) {const newObj = Object.create(obj)// 返回一个对象,并且这个对象的原型会指向 obj
return newObj
}
const obj = {name: 'peter'}
const obj1 = inherit3(obj)
console.log(obj1.name)
(3)寄生组合模式
function inherit(obj) {function middleFn() {}
middleFn.prototype = new obj()
return new middleFn()}
function inheritPrototype(sub, sup) {sub.prototype = inherit(sup)
sub.prototype.constructor.name = sub
}
inheritPrototype(Student, Person)
最初将 sub 的原型当中的 constructor 指向了 sub