六种继承的学习,敲得源码和注释都在下面,可以直接运行,方便更加直观的了解想继承
通过prototype去继承
注意事项
1、给原型添加方法的代码一定要放在替换原型的语句之后。
2、存在内存空间共享的问题,当存在属性为数组的时候,一个改变,另一个也会改变
function Animal(name){
this.friend=["ahua","amao"]
this.name = name
this.color = "yellow"
this.eat = function (food) {
console.log(this.name + "正在吃:" + food)
}
}
Animal.prototype.master = "小明"
function Dog() {
// this.color = "white"
}
function Cat() { }
// Dog.prototype.color = "AJJAJA"
Dog.prototype = new Animal()
Dog.prototype.name = "大黄"
var dog = new Dog()
dog.friend.push("aaa")
var dog2 = new Dog()
dog.eat('大骨头') //大黄正在吃:大骨头
console.log(dog.master)//小明
cat.eat('鱼儿')
Cat.prototype.color = "dsakdkjad"
Cat.prototype = new Animal()
Cat.prototype.name = "小咪"
var cat = new Cat()
console.log(dog.color)
console.log(dog instanceof Animal)
console.log(dog instanceof Dog)
onsole.log(cat instanceof Animal)
console.log(cat instanceof Cat)
二、构造函数继承 主要就是使用call实现的 ,call可以改变函数this的指向
// -----------------------------分割线---------------------------------------
function Animal(name){
this.friend=["ahua","amao"]
this.name = name
this.color = "yellow"
this.eat = function (food) {
console.log(this.name + "正在吃:" + food)
}
}
Animal.prototype.master = "小明"
function Fox(){
Animal.call(this)
this.color = "red"
this.name = "小狐狸"
}
let fox = new Fox()
let fox1 = new Fox()
// 解决了内存空间共享的问题
fox1.color="green"
console.log(fox.friend,fox1.friend)
//父类原型上新增的属性和方法不会被继承
console.log(fox.master,fox1.master)
// -----------------------------分割线---------------------------------------
思路就是使用原型链实现对原型属性和方法的继承
而通过借用构造函数来实现对实例属性的继承。
即通过在原型上定义方法实现了函数复用,又能够保证每个实例都有他自己的属性
解决了内存空间共享的问题,相较于构造函数,父类原型上的方法和属性都可以被继承
function Animal(name){
this.friend=["ahua","amao"]
this.name = name
this.color = "yellow"
this.eat = function (food) {
console.log(this.name + "正在吃:" + food)
}
}
Animal.prototype.master = "小明"
function Tiger (name,age){
Animal.call(this,name) //第二次调用
this.weight = age
}
Tiger.prototype = new Animal() //第一次调用
Tiger.prototype.sayName = function(){
alert(this.weight)
}
var littleTiger = new Tiger("xiaolaohu","dklsajdlk")
littleTiger.friend.push("xiaolaohu")
console.log(littleTiger.friend)
littleTiger.eat("DJSKAHD")
var littleTiger1 = new Tiger("xiaol大萨达aohu","dklsajdlk")
littleTiger1.friend.push("xiaol大萨达aohu")
console.log(littleTiger1.friend)
littleTiger1.eat("DJSKAHD")
// 组合继承也有缺点 父类执行了两次 多构造一次就会多一次开销,(性能问题)
// new了一次,call的时候一次
主要使用的是ES5的方法, Object.create(proto[,propertiesObject])
传入一个目标对象作为create的参数,会生成一个新对象。而这个新对象的__proto__是由目标对象提供的。
let Person = {
name:"xiaobei",
friends:["angel","xiaoxiao"]
}
// let aPerson = Object(Person)
let aPerson = Object.create(Person)
aPerson.name = "goushi"
aPerson.friends.push("dshaj")
// let Person1 = Object(Person)
let Person1 = Object.create(Person)
Person1.name = "PI"
Person1.friends.push("DKSAHD")
console.log(aPerson,Person1)
// 可以继承父类的属性和方法,还是存在空间共享的问题
创建一个仅用于封装继承过程的函数,该函数在内部以某种方式来增强对象,最后返回一个对象
function createAnother(original){
let clone = Object.create(original)
clone.sayHi = function(){
console.log("hi")
}
return clone
}
let persopn = {
name:"dhjsa",
friends:["dsahk","shajd"]
}
let ontherPerson = createAnother(persopn)
// ontherPerson.friends.push("dhsakj")
ontherPerson.name = "dshakd hads"
let ontherPerson1 = createAnother(persopn)
// ontherPerson1.friends.push("111")
ontherPerson1.name = "dshakd"
console.log(ontherPerson,ontherPerson1)
//缺点,依旧存在空间共享的问题
//适用于关注对象,不在乎类型和构造函数的场景,Object()函数不是寄生式继承所必须的
//任何返回新对象的函数都可以在这里使用
寄生式组合继承
通过借用构造函数继承属性,但使用混合式原型链继承方法
基本思路就是 取得父类原型的一个副本,使用寄生式继承来继承父类原型,
然后将返回的新对象赋值给子类原型,解决了内存共享的问题
function inheritPrototype(subType, superType) {
let prototype = Object.create(superType.prototype); // 创建对象,创建父类原型的一个副本
prototype.constructor = subType; // 增强对象,弥补因重写原型而失去的默认的constructor 属性
subType.prototype = prototype; // 指定对象,将新创建的对象赋值给子类的原型
}
// 父类初始化实例属性和原型属性
function superType(name) {
this.name = name;
this.colors = [1, 2, 3, 4, 5];
}
superType.prototype.saySuper = function () {
console.log("super");
};
// 借用构造函数传递增强子类实例属性(支持传参和避免篡改)
function subType(name, age) {
superType.call(this, name);
this.age = age;
}
subType.prototype.saySub = function () {
console.log("sub");
};
// 将父类原型指向子类
inheritPrototype(subType, superType);
let instance1 = new subType("zs", 10);
instance1.colors.push(10);
let instance2 = new subType("ls", 20);
instance2.colors.push(100);
console.log(instance1);
console.log(instance2)