版权声明:欢迎阅读,有误请指正,转载请申明。 https://blog.csdn.net/wx1995sss/article/details/87257080
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script>
// js的继承实现方式
// 原型链继承
// 构造继承
// 实例继承
// 拷贝继承
// 组合继承
// 寄生组合继承
//要实现继承,首先得要有一个父类
console.dir(Object);
function Animal(name){
this.name = name;//属性
this.walking = function(){
return this.name + "正在散步";
}
}
//原型方法
Animal.prototype.eat = function(food){
return this.name+"正在吃"+food;
}
//原型链的方法
//核心:将父类的实例作为子类原型
function Cat(){};
Cat.prototype = new Animal();
Cat.prototype.name = "小C";
var cat = new Cat();
console.log(cat.name);//小C
console.log(cat.eat("鱼"));//小C正在吃鱼
console.log(cat.walking());//小C正在散步
console.log(cat instanceof Animal);//true
console.log(cat instanceof Cat);//true
// 特点:
// 实例是子类的实例,也是父类的实例
// 父类新增的原型方法和原型属性,子类都可以访问得到
// 缺点:如果要给子类新增原型属性和方法,必须new 父类的后面才能执行
// 无法实现多继承
// 来自原型对象的所有属性被所有实例共享
// 创建子类实例的时候,没有办法向父类构造函数传参
/*构造继承
* 核心:使用父类的构造函数来增强子类实例,等于是复制父类的实例属性给予子类
*/
function Dog(name){
Animal.call(this);//属性使用对象冒充(call),实际上是改变this指针的指向,继承父类
//this相当于 new Dog()
//Students.call(this);
this.name = name;
}
var dog =new Dog("小D");
console.log(dog.name);//小D
console.log(dog.walking());//小D正在散步
//console.log(dog.eat("肉"));报错,不使用原型
console.log(dog instanceof Animal);//false
console.log(dog instanceof Dog);//true
/*特点
* 可以实现多继承(call多个父类对象)
* 创建子类实例的时候,可以先向父类传参
* 缺点:
* 不能访问父类原型方法
* 实例是子类的实例,不是父类实例
* 无法实现函数复用,每个子类都有父类实例函数的副本,影响性能
*/
/*实例继承
* 核心:为父类实例添加新特征,作为子类实例返回
*/
function Sheep(name){
var anim = new Animal();//创建父类的实例
anim.name = name;//给实例添加属性
return anim;//返回属性
}
var sheep =new Sheep("小D");
console.log(sheep.name);//小D
console.log(sheep.walking());//小D正在散步
console.log(sheep.eat("草"));//小D正在吃草
console.log(sheep instanceof Animal);//true
console.log(sheep instanceof Sheep);//false
/*特点
* 不限制调用方法,不管是new 子类()还是直接子类(),返回的对象具有相同的效果
* 缺点
* 实例是父类的实例,不是子类的实例
* 没有办法实现多继承
*/
/*拷贝继承
* 支持多继承,效率很低,内存占用高(拷贝父类的属性),无法获取父类不可枚举的方法
*/
/*组合继承
* 核心:通过调用父类构造函数,继承父类的属性并保留传参的优点
* 然后通过将父类的实例作为子类原型,实现函数复用
*/
function Rubbit(name){
Animal.call(this);
this.name = name;
}
Rubbit.prototype = new Animal();
Rubbit.prototype.constructor = Rubbit;//修复构造函数的指向(组合继承要构造函数的指向)
var rubbit = new Rubbit("小R");
console.log(rubbit.name);//小R
console.log(rubbit.walking());//小R正在散步
console.log(rubbit.eat("草"));//小R正在吃草
console.log(rubbit instanceof Animal);//true
console.log(rubbit instanceof Rubbit);//true
/*特点
* 可以多继承
* 实例是子类的实例也是父类的实例
* 可传参
* 函数可复用
* 可以继承实例的属性和方法,也可以继承原型的属性和方法
* 缺点
* 调用了两次父类构造函数,生成了两份实例,稍微多占了一些内存
*/
/*寄生组合继承
* 核心:通过寄生方式,砍掉父类的实例属性,这样,在调用两次父类的构造的时候就不会初始化两次实例方法和属性,避免了组合继承的缺点
*/
function Fox(name){
Animal.call(this);
this.name =name;
}
(function(){
//创建一个没有实例方法的类
var obj = function(){};
//将子类的原型指向父类的原型
obj.prototype = Animal.prototype;
//将创建的没有实例方法的类的实例作为构造函数Fox子类的原型
Fox.prototype = new obj();
})();
var fox = new Fox("小F");
Fox.prototype.constructor =Fox;//修复构造函数的指向
console.log(fox.name);//小F
console.log(fox.walking());//小F正在散步
console.log(fox.eat("鸡"));//小F正在吃鸡
console.log(fox instanceof Animal);//true
console.log(fox instanceof Fox);//true
/*现在有两个类即构造函数,一个是动物类,一个是猫类,
怎么样让猫类继承动物类的所有属性和方法呢 */
function Animals() {
this.species = "动物";
}
function Cats(name, color) {
this.name = name;
this.color = color;
}
//原型链继承
/*Cats.prototype = new Animals();
var cats = new Cats("深毛","黄色");
console.log(cats.species);*/
//组合继承
// Cats.prototype = new Animals();
// Cats.prototype.constructor = Cats;
// var cats = new Cats("深毛","黄色");
// alert(cats.species);
//寄生组合继承
function Cats(name, color){
Animals.call(this);
this.name = name;
this.color = color;
}
(function(){
var objs = function(){};
objs.prototype = Animals.prototype;
console.log(Animals.prototype);//{constructor: ƒ}
console.log(Cats.prototype);//{constructor: ƒ}
Cats.prototype = new objs();
// Cats.prototype = objs.prototype; 将上面的改为此式,一样有效
//原型是对象属性的备用来源。
//每个对象除了拥有自己的属性外,几乎都包含一个原型。原型是另一个对象,是对象的一个属性来源。
//当开发人员访问一个对象不包含的属性时,就会从对象原型中搜索属性,接着是原型的原型,依此类推。
//所以这里new objs()没有属性,Cats.prototype访问了 objs()的原型,即objs.prototype
console.log(new objs());//objs {}
console.log(Cats.prototype);//Animals {}
console.log(Cats.prototype.constructor);//ƒ Animals() { this.species = "动物"; }
})();
Cats.prototype.constructor = Cats;//这里Cats的原型是Animals,constructor是Cats,constructor存储着原型的指针,即Cats能同时访问Animals和自身
var cats = new Cats("深毛","黄色");
console.log(cats.species);
console.log(cats.color);
console.log(cats.name);
console.log(Cats.prototype);//Animals {constructor: ƒ}
console.log(Cats.prototype.constructor);//ƒ Cats(name, color){Animals.call(this);this.name = name; this.color = color; }
</script>
</head>
<body>
</body>
</html>