原型继承
首先创建一个构造函数,并为其设置私有属性和公有属性。
// 定义一个人类
function Person (name) {
// 属性
this.name = name;
// 实例方法
this.sleep = function(){
console.log(this.name + '正在睡觉!');
}
}
// 原型方法
Person.prototype.eat = function(food) {
console.log(this.name + '正在吃:' + food);
};
开始继承
原型继承有很多种方法,接下来就记录下我已知的几种方法。
第一种 原型链继承
重点圈起来:将父类实例赋值给子类原型对象
// 创建子类、添加子类属性。
function arrange(name){
this.name = name;
this.goShop = function(food){
console.log(name + '叫你去买'+ food)
}
}
// 将父类实例赋值给子类原型对象
arrange.prototype = new Person();
// 将constructor指向本身,保证原型链不断。
arrange.prototype.constructor = arrange;
//创建arrange新实例,也是Person实例;
var newObj = new arrange('李四');
console.log(newObj instanceof Person) //true
console.log(newObj instanceof arrange) //true
// 原型链继承成功,可以访问父类所有属性;
console.log(newObj)
console.log(newObj.name) // 李四
newObj.sleep(); // 李四正在睡觉!
newObj.eat('苹果'); // 李四正在吃:苹果
newObj.goShop('香蕉'); // 李四叫你去买香蕉
第二种 构造继承
重点圈起来:执行父构造,将This指向本身,拉取父私有属性
// 创建子类、添加子类属性。
function arrange(name){
Person.call(this,name) // 执行父构造,将This指向本身,拉取父私有属性;
}
arrange.prototype.getName = function(){
console.log('我叫' + this.name)
}
var newObj = new arrange('李四');
console.log(newObj)
console.log(newObj.name) //李四
newObj.sleep() // 李四正在睡觉!
newObj.getName() //我叫李四
第三种 组合继承
重点圈起来:构造继承与原型继承组合。注意注释区域,切勿在继承时使用此方法重写或添加方法,否则将会修改整个原型,导致崩塌。
// 创建子类、添加子类属性。
function arrange(name){
Person.call(this,name) // 执行父构造,将This指向本身,拉取父私有属性;
}
// 将父类实例赋值给子类原型对象
arrange.prototype = new Person(); // 直接拉取父类实例继承原型
// 将constructor指向本身,保证原型链不断。
arrange.prototype.constructor = arrange;
// 下面这个方法会替换整个原型对象
// arrange.prototype = {
// init:function(){
// console.log('我会替换整个原型')
// }
// }
// 必须在原型实例继承之后,在给子类原型添加方法,或重写方法,请使用以下方法
arrange.prototype.eat = function() {
console.log(this.name + '重写了此方法');
};
arrange.prototype.addFn = function(){
console.log(this.name + '添加了新方法' );
}
var newObj = new arrange('王五');
console.log(newObj)
newObj.eat(); // 王五重写了此方法
newObj.addFn(); // 王五添加了新方法
第四种 克隆原型链继承
重点圈起来: 将等待继承的原型对象克隆,再赋值给继承的原型对象。此种方法会脱轨,不在同一原型链上
// 创建子类、添加子类属性。
function arrange(name){
this.name = name;
this.goShop = function(food){
console.log(name + '叫你去买'+ food)
}
}
// 创建克隆类型
function Clone(obj){
for(var key in obj){
this[key] = typeof obj[key] == 'object' ? new Clone(obj[key]) : obj[key];
}
}
// 使用Clone构造函数继承原型
arrange.prototype = new Clone(Person.prototype);
// 将constructor指向本身,保证原型链不断。
arrange.prototype.constructor = arrange;
//创建arrange新实例,也是Clone实例,却不在是Person实例;
var newObj = new arrange('李四');
console.log(newObj instanceof Person) //false
console.log(newObj instanceof arrange) //true
console.log(newObj instanceof Clone) //true
// 克隆成功,可以访问克隆对象的原型对象;
console.log(newObj)
console.log(newObj.name) // 李四
newObj.eat('苹果'); // 李四正在吃:苹果
newObj.goShop('香蕉'); // 李四叫你去买香蕉
第五种 寄生组合继承
重点圈起来: 将父类原型对象直接赋值给一个空属性的构造函数,再将空属性的构造函数实例赋值给子类原型对象,其根本是为了解决父实例继承的出现的两次构造。
// 创建子类、添加子类属性。
function arrange(name){
Person.call(this,name)
this.shop = function(){
console.log(this.name + '去买好吃的,好吃就多吃点')
}
}
(function(){
// 创建一个没有实例方法的类
var nullFn = function(){};
nullFn.prototype = Person.prototype;
//将实例作为子类的原型
arrange.prototype = new nullFn();
// 将constructor指向本身,保证原型链不断。
arrange.prototype.constructor = arrange;
})();
var newObj = new arrange('老王');
console.log(newObj)
newObj.shop(); // 老王去买好吃的,好吃就多吃点
newObj.sleep(); // 老王正在睡觉!
newObj.eat('芭蕉'); // 老王正在吃:芭蕉
学习犹如逆水行舟,有舟就上。别问为什么,吾乃不踩坑学不会系列。