前端面试:用ES5实现类的继承。

首先科普一下new方法的本质:

    var new2 = function(func){
      var o = Object.create(func.prototype);//先以func原型为模版创建一个对象
      var k = func.call(o);//再以该对象为this传入构造函数
      if(typeof k === 'object'){
        return k
      }else{
        return o
      }
    }

第一种方式是借助构造函数实现继承:

  function Parent1(){
    this.name = 'parent1';
  }
  function Child1(){
    Parent1.call(this);
    this.type = 'child1'
  }
  console.log(new Child1);

这样写的时候子类虽然能够拿到父类的属性值,但是问题是父类中一旦存在方法那么子类无法继承。那么引出下面的方法。

第二种方式借助原型链实现继承:

  function Parent2() {
    this.name = 'parent2';
    this.play = [1, 2, 3]
  }
  function Child2() {
    this.type = 'child2';
  }
  Child2.prototype = new Parent2();

  console.log(new Child2());

看似没有问题,父类的方法和属性都能够访问,但实际上有一个潜在的不足。举个例子:

  var s1 = new Child2();
  var s2 = new Child2();
  s1.play.push(4);
  console.log(s1.play, s2.play);
 

可以看到控制台:

明明我只改变了s1的play属性,为什么s2也跟着变了呢?很简单,因为两个实例使用的是同一个原型对象。

那么还有更好的方式么?

第三种方式:将前两种组合:我,

  function Parent3 () {
    this.name = 'parent3';
    this.play = [1, 2, 3];
  }
  function Child3() {
    Parent3.call(this);
    this.type = 'child3';
  }
  Child3.prototype = new Parent3();
  var s3 = new Child3();
  var s4 = new Child3();
  s3.play.push(4);
  console.log(s3.play, s4.play);

可以看到控制台:

之前的问题都得以解决。但是这里又徒增了一个新问题,那就是new Child3的过程中,根据new的过程,Parent3的构造函数会被执行两次。这是我们不愿看到的。那么如何解决这个问题?

第四种方式: 组合继承的优化1

  function Parent4 () {
    this.name = 'parent4';
    this.play = [1, 2, 3];
  }
  function Child4() {
    Parent4.call(this);
    this.type = 'child4';
  }
  Child4.prototype = Parent4.prototype;

这里让将父类原型对象直接给到子类,父类构造函数只执行一次,而且父类属性和方法均能访问,但是我们来测试一下:

  var s3 = new Child4();
  var s4 = new Child4();
  console.log(s3)

子类实例的构造函数是Parent4,显然这是不对的,应该是Child4。

第五种方式(最推荐使用):优化2

  function Parent5 () {
    this.name = 'parent5';
    this.play = [1, 2, 3];
  }
  function Child5() {
    Parent5.call(this);
    this.type = 'child5';
  }
  Child5.prototype = Object.create(Parent5.prototype);
  Child5.prototype.constructor = Child5;

这是最推荐的一种方式,接近完美的继承。

因此,小小的继承虽然ES6当中简化了很多,但毋庸置疑的是,js是一门基于原型的语言,所以,用ES5来完成继承非常考验面试者对JS语言本身的理解,尤其是对于原型链是否理解清楚。另外,在面试过程中最好把这几种方式都向面试官展示出来,大概需要十分钟左右,以体现自己对于原型链的理解到位,因为在有限的面试时间中,并不是回答的问题越多越好,而是最大化地展示自己扎实的基础和知识的深度,这是让面试官赏识自己的关键。

猜你喜欢

转载自blog.csdn.net/weixin_42098339/article/details/87900369