JS 实现继承的几种方式
原型的指向
首先我定义了一个Person自定义构造函数,并且在原型上添加了一个eat方法
定义了一个Student 函数,在原型上定义了一个sayHi方法
然后我将 Student的原型指向 了一个 Person的实例对象
接着实例化一个Student,接着分别在stu 实例上 尝试着调用 eat方法 和 sayHi 方法
stu实例对象指向person的实例对象,所以你为student添加方法,必须在指向完再重新添加
stu实例对象指向person的实例对象,所以你为student添加方法,必须在指向完再重新添加
prototype 实现继承
var person = function (name, age) {
this.name = name
this.age = age
}
person.prototype.eat = function (params) {
console.log('eat')
}
var student = function (obj) {
this.obj = obj
}
student.prototype.play = function (params) {
console.log('play')
}
var stu1 = new student('china')
stu1.prototype = new person('xixi',18)
console.log(stu1)
//用点的方式在对象上加方法
student.prototype.eat = function () {}
//直接在对象上加方法,constructor会消失,所以要重新指一下
student.prototype = {
sleep:function(){
console.log('sleep')
}
}
student.prototype.constructor = student
var stu2 = new student('amer')
console.log(stu2)
所以需要重新指一下。
student.prototype.constructor = student
利用 call 借用构造函数继承
缺点:引用类型的内存空间共享的
function person(name, age) {
this.name = name
this.age = age
}
person.prototype.eat = function (params) {
console.log('eat')
}
function student (obj) {
this.obj = obj
}
student.prototype = new person('hehe',[0,1])
var stu1 = new student('tt')
stu1.name = 'jj'
stu1.age.push(7)
var stu2 = new student('kk')
console.log(stu1)
console.log(stu2)
console.log(new person())
组合继承
没有call和constructor重新指向
function teacher () {
this.work = [0]
}
function xiaochang(){
this.school = 'school'
}
xiaochang.prototype = new teacher()
var tea1 = new xiaochang()
tea1.work.push(9)
var tea2 = new xiaochang()
console.log(tea1)
console.log(tea2)
call和constructor重新指向
function teacher () {
this.work = [0]
}
function xiaochang(){
teacher.call(this)
this.school = 'school'
}
xiaochang.prototype = new teacher()
xiaochang.prototype.constructor = xiaochang
var tea1 = new xiaochang()
tea1.work.push(9)
var tea2 = new xiaochang()
console.log(tea1)
console.log(tea2)
function teacher (work) {
this.work = work
}
function xiaochang(work,school){
teacher.call(this,work)
this.school = school
}
xiaochang.prototype = new teacher()
xiaochang.prototype.constructor = xiaochang
var tea1 = new xiaochang([0],'xiamen')
tea1.work.push(9)
var tea2 = new xiaochang([9],'fujian')
console.log(tea1)
console.log(tea2)
直接继承prototype
function Person(name,age,sex){
this.name=name;
this.age=age;
this.sex=sex;
}
Person.prototype.sayHi=function(){
console.log("你好")
function Student(name,age,sex,score){
//借用构造函数
Person.call(this,name,age,sex)
this.score=score
}
Student.prototype = Person.prototype
var stu = new Student("小黑",20,"男","100分")
console.log(stu)
原型式继承
这里不得不提到的就是 ES5 里面的 Object.create 方法,这个方法接收两个参数:一是用作新对象原型的对象、二是为新对象定义额外属性的对象(可选参数)。
其实 Object.create 方法是可以为一些对象实现浅拷贝的。
寄生式继承
对于普通对象的继承方式来说,寄生式继承相比于原型式继承,还是在父类基础上添加了更多的方法
function clone(original) {
let clone = Object.create(original);
clone.getFriends = function() {
//这里是this指clone
return this.friends;
};
clone.getName = function() {
//这里是this指clone
return this.name;
};
return clone;
}
寄生组合式继承
function person(name, age) {
this.name = name
this.age = age
}
person.prototype.eat = function (params) {
console.log('eat')
}
function clone (child,parents){
//浅复制父类
let clone = Object.create(parents);
//clone的原型对象指向父类的原型对象,继承父类上的方法
clone.prototype = parents.prototype
//子类的原型对象的构造方法指向clone
child.prototype.constructor = clone
}
function clone2(child,parents) {
//浅复制父类的原型对象
let clone = Object.create(parents.prototype)
//clone的构造函数constructor指向子类
clone.constructor = child
//子类的prototype指向clone
child.prototype = clone
}
function student (name,age,obj) {
person.call(this,name,age)
this.obj = obj
}
function student1 (name,age,obj,work) {
person.call(this,name,age)
this.obj = obj
this.work = work
}
clone(student,person)
clone(student1,person)
student.prototype.say = function () {
console.log('say')
}
student1.prototype.sleep = function (params) {
console.log('sleep')
}
var stud = new student('kk',[0,1],'hehe')
console.log(stud)
var studd = new student1('jj',78,'hh','teacher')
console.log(studd)
ES6 的 extends 关键字实现逻辑
因为浏览器的兼容性问题,如果遇到不支持 ES6 的浏览器,那么就得利用 babel 这个编译工具,将 ES6 的代码编译成 ES5,让一些不支持新语法的浏览器也能运行。
class person {
constructor(name, age){
this.name = name
this.age = age
}
eat = function (params) {
console.log('eat')
return this
}
}
class student extends person{
constructor(name,age,obj) {
super(name,age)
this.obj = obj
}
say = function () {
console.log('say')
}
}
var stud = new student('kk',[0,1],'hehe')
console.log(stud.eat())