JS的继承

拖了好久的JS继承终于来个总结了T^Tjavascript

本篇文章参考阮一峰老师的博文。一共有三篇。html

1、先说一下prototype对象java

function Cat(name, age){
    this.name = name;
    this.age = age;
    this.speak = function () {
        console.log(this.name + ' miao');
    }
}

var cat1 = new Cat('Tom', 1);
var cat2 = new Cat('John', 2);
console.log(cat1.speak());    // Tom miao
console.log(cat2.speak());    // John miao

上面代码中的两个实例,cat1 和 cat2 都有本身的name属性,age属性,speak方法,可是其实speak方法实能够共用的,这样就会形成了资源浪费。避免这种浪费,咱们能够把 speak 方法写入构造函数的 prototype 对象中。app

function Cat(name, age){
    this.name = name;
    this.age = age;
}

Cat.prototype.speak = function(){
    console.log(this.name + ' miao');
}

var cat1 = new Cat('Tom', 1);
var cat2 = new Cat('John', 2);

将能够共享的方法挂载在原型对象上,就能够避免出现内存浪费的现象了函数

Cat.prototype.speak = function() {
    console.log(this.name + ' miao');
}

Cat.prototype.eat = 'fish';

cat2.prototype.eat = 'meat';


// 问题来了,若是我改变其中一个实例的原型上的属性和方法,那么另外一个原型会不会收到影响呢

答案是不会!!!this

 

 

 可是,若是修改的是 cat2.__proto__.eat,那么就会对 cat1 有影响了spa

 

 

 这里可能有点迷!!!是的,我有点迷~~~~~~~prototype

我是这样子理解的3d

由于建立实例须要用到 new 操做符,那么 new 中间做了什么妖呢code

  • 建立了一个新对象
  • 将新对象的__proto__属性指向构造函数的原型对象,新对象就新增了构造函数原型对象上的属性和方法
  • 将构造函数的this指向替换成新对象,再执行构造函数,这样新对象就新增了构造函数本地的属性和方法了
    // 模拟 new
    var obj = {};
    obj.__proto__ = 构造函数.prototype;
    构造函数.apply(obj);

     

那么看会又来的构造函数 Cat,我画了这样一幅图

 

 

2、JS继承

  1. 原型链继承——将父类的实例做为子类的原型
    function Animal(name){
        this.name = name;
    }
    Animal.propotype = {
        canRun: function(){
            console.log(this.name + ' can run.');
        }
    }
    function Cat(){
        this.speck = 'miao';
    }
    Cat.prototype = new Animal('Tom');
    Cat.prototype.constructor = Cat;

    我以为应该会有人有和我同样的疑惑。为何会有Cat.prototype.constructor = Cat的出现。

     由于咱们把父类Animal的实例做为了子类Cat的原型对象,所以若是没有Cat.prototype.constructor = Cat,Cat.prototype.constructor就会指向Animal,形成继承链的混乱,因此咱们须要手动纠正。

    2. 构造继承——改变this的指向,用apply或者call方法实现

    

function Animal(name){
    this.name = name;
}
Animal.prototype = {
    canRun: function(){
        console.log(this.name + ' it can run!');
    }
}
function Cat(name){
    Animal.call(this, name);
    this.speak = 'miao';
}
var cat1 = new Cat('Tom');

    这个继承方法有一个很差,就是子类没法继承父类原型上的属性和方法,也就是说 cat1.canRun()会出错。

 

 

         3. 组合继承——将原型链继承和构造继承结合到一块

    

function Animal(name){
    this.name = name;
}
Animal.prototype = {
    canRun: function(){
        console.log(this.name + 'is can run!');
    }
}
function Cat(name, age){
    Animal.call(this, name);
    this.speak = 'miao';
    this.age = age;
}
Cat.prototype = new Animal();
Cat.prototype.constructor = Cat;
var cat1 = new Cat('Tom', 12);
相关文章
相关标签/搜索