js中类的继承

在学习js类的继承之前,首先查找学习了一些前置知识

一、js中定义类的写法:

function Person(name){
this.name = name;
}
Person.prototype.getName = function(){
return this.name;
}
实例化:var person = new Person("tom");

二、关于prototype:

每一个构造函数(如Person)都有一个prototype属性,这个属性就是对象实例(如person)的原型对象

调用某一方法时,若该方法在对象实例中不存在,就会去原型对象中查找,因此在原型对象中定义所有对象实例公用的属性与方法

prototype 对于构造函数来说,它是一个属性,对于对象实例来说,它是一个原型对象

三、原型链:

原型对象对于实例对象来说,它自身也是对象,也有自己的原型,形成了一条原型链。所有一切对象的顶端都是Object.prototype,

读取某个对象的属性时,会先寻找该对象自身的属性,若没有,则会去它的原型对象中寻找,原型中也没有,就去原型的原型中找,直至顶层的Object.prototype,若还是没有,就返回undefined

四、Constructor属性

prototype有一个属性constructor,默认指向prototype对象所在的构造函数

A.prototype.constructor === A

四、call方法

扩充函数运行的作用域,改变函数中this关键字的指向(指向传入的参数)

<script>

//例1

window.color = "red";

document.color="white";



function printColor(){

console.log(this.color);

}



printColor.call(window);//red

printColor.call(document);//white

//例2

var Animal = {

word : '...',

speak : function(){

console.log(this.word);

}

}



Animal.speak();//...

var Dog={ word : 'wang'}

Animal.speak.call(Dog);//wang

</script>

搞懂了前面这些知识点,便于我们更加容易理解和学习js的几种继承方式的写法

JS继承的实现方式

首先写一个父类

扫描二维码关注公众号,回复: 5124453 查看本文章
父类

function Father(name){

this.name = name || 'defaultName';

this.gender = [];

}

Father.prototype.eat = function(food){

console.log(this.name+":"+food);

}

1.原型链继承

function Son(){}

Son.prototype = new Father();

Son.prototype.name='Son';



var son1 = new Son();

var son2 = new Son();

son1.eat("rice");//Son:rice

son2.eat("noddle");//Son:noddle

son1.gender.push('male');

console.log(son1.gender);//["male"]

缺点:1.来自父类(原型对象)的引用属性被所有子类实例共享,在修改son1的gender属性,son2的gender属性随之改变

2.创建子类实例时,无法向父类构造函数传参

2.构造继承

function Son(){

Father.call(this);

}



var son = new Son();

son.eat("rice");//Uncaught TypeError: son.eat is not a function

console.log(son.name);//defaultName

console.log(son instanceof Father);//false

console.log(son instanceof Son);//true

创建子类实例时,可以向父类构造传参;子类实例不再共享父类的引用属性

缺点:1.子类无法继承原型属性和方法

2.创建的子类实例并不是父类的实例

3.组合继承

function Son(name){

Father.call(this);

this.name = name || 'sonName';

}

Son.prototype = new Father();

Son.prototype.constructor = Son;//修复构造函数指向



var son1 = new Son();

var son2 = new Son("Tom");

son1.eat('rice');//sonName:rice

son2.eat('rice');//Tom:rice

son1.gender.push('male');

console.log(son2.gender);//[]

console.log(son1 instanceof Son);//true

console.log(son1 instanceof Father);//true

解决了原型链继承和构造继承中存在的问题,只是调用了两次父类构造函数

4.实例继承

function Son(){

var instance = new Father;

instance.name = 'Son';

return instance;

}



var son = new Son();

console.log(son.name);//Son

console.log(son instanceof Son);//false

console.log(son instanceof Father);//true

重写父类的属性

缺点:创建的实例不是子类的实例

5.拷贝继承

function Son(name){

var father = new Father();

for(var p in father){

Son.prototype[p] = Father[p];

}

Son.prototype.name = name || 'sonName';

}

var son = new Son();

console.log(son.name);//sonName

console.log(son instanceof Father); // false

console.log(son instanceof Son); // true

遍历父类属性,逐一拷贝到子类中

6.寄生组合继承

function Son(name){

Father.call(this);

this.name = name || 'sonName';

}

(function(){

// 创建一个没有实例方法的类

var Super = function(){};

Super.prototype = Father.prototype;

//将实例作为子类的原型

Son.prototype = new Super();

})();

Son.prototype.constructor = Son;//修复构造函数指向



var son1 = new Son();

var son2 = new Son("Tom");

son1.eat('rice');//sonName:rice

son2.eat('rice');//Tom:rice

son1.gender.push('male');

console.log(son2.gender);//[]

console.log(son1 instanceof Son);//true

console.log(son1 instanceof Father);//true

解决了组合继承中存在的问题

参考:https://www.cnblogs.com/humin/p/4556820.htmlJS实现继承的几种方式

https://blog.csdn.net/ganyingxie123456/article/details/70855586(JS中的call()方法和apply()方法用法总结)

https://www.jb51.net/article/91826.htm(详解Javascript中prototype属性(推荐))

猜你喜欢

转载自blog.csdn.net/weixin_39463716/article/details/81227556