Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

关于es5、es6继承的一些认知 #1

Open
sfsoul opened this issue Jun 16, 2018 · 3 comments
Open

关于es5、es6继承的一些认知 #1

sfsoul opened this issue Jun 16, 2018 · 3 comments
Labels
日常分享 个人记录

Comments

@sfsoul
Copy link
Owner

sfsoul commented Jun 16, 2018

缘由

因为最近一直在准备面试,所以对js基础方面的东西又加深了一些了解,因此想通过自己的认知将学到的东西写下来。js继承这块一直是面试的重点,这篇文章的就是基于看了冴羽的博客博客地址后加上了自己的想法写的。


正文

先写一个个人认为目前最好的继承

    //父类构造函数
    function Father(name){
        this.name = name;
    }

    //父类原型上方法
    Father.prototype.getName = function(){
        console.log(this.name);
    };

    //子类构造函数
    function Child(name,age){
        Father.call(this,name); //为实例添加name属性
        this.age = age;
    }

    Child.prototype = Object.create(Father.prototype); //使得 Child.prototype.__proto__ === Father.prototype
    Child.prototype.constructor = Child; //重新修改Child.prototype指向
    Child.prototype.getAge = function(){
        console.log(this.age);
    };

    var child = new Child("zj",25);
    console.log(child);

    console.log(child.__proto__ === Child.prototype);  //true
    console.log(Child.prototype.__proto__ === Father.prototype); //true
    console.log(child.constructor === Child); //true
    console.log(Child.prototype.constructor === Child); //true

原型链继承

再来看看原型链继承的缺点

  • 引用类型的属性被所有实例共享
  • 在创建 Child 的实例时,不能向Parent传参

这边直接拷贝冴羽大神那块的代码

    function Parent(){
        this.names = ["zj","dmy"];
    }

    Parent.prototype.getName = function(){
        console.log(this.name);
    }

    function Child(){}

    Child.prototype = new Parent(); //实现继承。相当于 Child.prototype.__proto__ === Parent.prototype

    var child1 = new Child();
    var child2 = new Child();
    console.log(child1);
    console.log(child2);

原型链继承

首先从上面的代码以及截图中来分析原型链继承的第一个缺点(引用类型被所有实例共享)。
因为child1、child2两个实例对象自身并没有names这个属性,所以输出child1.names、child2.names的时候,其实本质上它们都要去原型上查找,即Child.prototype.names。


借用构造函数继承

  • 缺点:方法都在构造函数中定义,每次创建实例都会创建一遍方法。
    function Father(name){
        this.name = name;
        this.getName = function(){
            console.log(this.name);
        }
    }

    function Child(name,age){
        Father.call(this,name);
        this.age = age;
    }

    var child1 = new Child("zj",25);
    var child2 = new Child("dmy",25);
    console.log(child1);
    console.log(child2);

构造函数继承

从图上可以看出child1和child2这两个实例都各自拥有各自的getName方法,而不是通过访问Child.prototype原型上得来的,这样每次创建实例的时候都需要为每个实例都创建很多方法(若方法很多的情况下),这样太不好啦。而且方法只能写在构造函数里面,不能把方法写在原型上Father.prototype.getName定义,因为实例并不能得到通过原型方式定义的方法。


使实例化与new无关

类的实例化,一个强制要求的行为,就是需要使用new操作符。如果不使用new操作符,那么构造器内的this指向,将不是当前的实例化对象。 优化的方式,就是使用instanceof做一层防护。

function Toast(option){
  if(!(this instanceof Toast)){
    throw new Error('Toast instantiation error');
  }
  
  this.prompt = '';
  this.elem = null;
  this.init(option);
}

强制调用者用new关键字来调用Toast函数。直接调用Toast函数就会报错。

参考文章来源

JavaScript深入之继承的多种方式和优缺点

@mqyqingfeng
Copy link

要坚持下来呦~ 与你共勉~ o( ̄▽ ̄)d

@mqyqingfeng
Copy link

此外,要不要订阅我的人工催更服务?(๑•̀ㅂ•́)و✧

@sfsoul
Copy link
Owner Author

sfsoul commented Jun 19, 2018

恩恩,我会坚持的~

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
日常分享 个人记录
Projects
None yet
Development

No branches or pull requests

2 participants