js继承方法之原型链继承

// 定义一个动物类
function Animal (name) {
  // 属性
  this.name = name || 'Animal';
  // 实例方法
  this.sleep = function(){
    console.log(this.name + '正在睡觉!');
  }
}
// 原型方法
Animal.prototype.eat = function(food) {
  console.log(this.name + '正在吃:' + food);
};

函数里this的属性 和 函数外prototype的属性,在new之后,都会被子类继承

function Cat(){ 
}
Cat.prototype = new Animal();
Cat.prototype.name = 'cat';

// Test Code
var cat = new Cat();
console.log(cat.name); //cat
console.log(cat.eat('fish')); //cat正在吃:fish
console.log(cat.sleep()); //cat正在睡觉!
console.log(cat instanceof Animal); //true 
console.log(cat instanceof Cat); //true

需要注意的是,原型链的继承方式,创建子类时,无法像父类构造传参,而且来自原型对象的引用属性是所有实例共享的,测试代码如下

function Animal (name) {
  // 属性
  this.name = name || 'Animal';
  // 实例方法
  this.sleep = function(){
    console.log(this.name + '正在睡觉!');
  }
  //实例引用属性
  this.features = [];
}
function Cat(name){
}
Cat.prototype = new Animal();

var tom = new Cat('Tom'); //创建子类的时候传参数,看下面输出,有没有效果
var kissy = new Cat('Kissy');

console.log(tom.name); // "Animal"  说明传参没有效果
console.log(kissy.name); // "Animal"
console.log(tom.features); // []
console.log(kissy.features); // []

tom.name = 'Tom-New Name';
tom.features.push('eat');

//针对父类实例值类型成员的更改,不影响
console.log(tom.name); // "Tom-New Name"
console.log(kissy.name); // "Animal"
//针对父类实例引用类型成员的更改,会通过影响其他子类实例
console.log(tom.features); // ['eat']
console.log(kissy.features); // ['eat']

原因分析:

关键点:属性查找过程

执行tom.features.push,首先找tom对象的实例属性(找不到),
那么去原型对象中找,也就是Animal的实例。发现有,那么就直接在这个对象的
features属性中插入值。
在console.log(kissy.features); 的时候。同上,kissy实例上没有,那么去原型上找。
刚好原型上有,就直接返回,但是注意,这个原型对象中features属性值已经变化了。
function Animal(name){
  this.name=name
}
Animal.prototype.eat = function(food){
  console.log(this.name + '吃' + food)
}

function Cat(){}
Cat.prototype = new Animal();
Cat.prototype.name = '猫';

let final = new Cat();//无法在这里像父类传参
final.eat('鱼') // 输出 "猫吃鱼"

摘录自 http://www.cnblogs.com/humin/p/4556820.html

你可能感兴趣的:(js继承方法之原型链继承)