JS的继承

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

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

一、先说一下prototype对象

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 对象中。

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

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

var cat1 = new Cat(Tom,2);

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

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

Cat.prototype.eat = fish;

cat2.prototype.eat = meat;


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

答案是不会!!!

分享图片

 

 

 但是,如果修改的是 cat2.__proto__.eat,那么就会对 cat1 有影响了

分享图片

 

 

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

我是这样子理解的

因为创建实例需要用到 new 操作符,那么 new 中间作了什么妖呢

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

     

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

分享图片

 

 

二、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);

相关文章

前言 做过web项目开发的人对layer弹层组件肯定不陌生,作为l...
前言 前端表单校验是过滤无效数据、假数据、有毒数据的第一步...
前言 图片上传是web项目常见的需求,我基于之前的博客的代码...
前言 导出Excel文件这个功能,通常都是在后端实现返回前端一...
前言 众所周知,js是单线程的,从上往下,从左往右依次执行,...
前言 项目开发中,我们可能会碰到这样的需求:select标签,禁...