(六)前端面试:面向对象

文章内容参考自《前端跳槽面试必备技巧》 

1.类的声明

  /**
   * 类的声明
   */
  function Animal() {
    this.name = 'name';
  }

  /**
   * ES6中的类声明
   */
  class Animal2 {
    constructor () {
      this.name = 'name';
    }
  }

  /**
   * 实例化
   */
  console.log(new Animal(), new Animal2()); // 如果没有参数,可以省略括号,即new Animal

2.类的继承

(1)ES6实现继承

  /**
   *  ES6 继承
   */
  class AnimalChildren extends Animal2 {
    add() {
       console.log(this.name); // 调用Animal2中的属性
    }
  }
  console.log((new AnimalChildren()).add()); // name

这个比较简单,不用太多介绍

(2)借助构造函数实现继承

  /**
   * 1.借助构造函数实现继承
   */
  function Parent1() {
    this.name = 'parent1';
  }
  Parent1.prototype.say = function () {}; // 无法继承此原型对象上的方法或属性
  function Child1() {
    Parent1.call(this); // 或者apply,这两个方法都是让Parent1构造函数的this重新定义到Child1上,因此,Child1就具有name属性
    this.type = 'child1';
  }
  // console.log(new Child1(), new Child1().say()); // new Child1().say()无法执行

这个方法有个缺点就是无法继承此原型对象上的方法或属性

(3)借助原型链实现继承

  /**
   * 2.借助原型链实现继承
   */
  function Parent2() {
    this.name = 'parent2';
    this.play = [1, 2, 3];
  }
  function Child2() {
    this.type = 'child2';
  }
  Child2.prototype = new Parent2(); // Child2的原型对象赋值为Parent2的实例
  console.log(new Child2());
  var s1 = new Child2();
  var s2 = new Child2();
  console.log(s1.play, s2.play); // [1, 2, 3]  [1, 2, 3]
  s1.play.push(4); // 会改变s2的值 原因:s1.__proto__ === s2.__proto__
  console.log(s1.play, s2.play); // [1, 2, 3, 4]  [1, 2, 3, 4]

这种方法的缺点就在于,改变某个子类实例中存在于父类中的方法或属性,会导致其子类的所有实例跟着发生改变

(4)组合方式实现

  /**
   * 3.组合方式实现继承
   */
  function Parent3() {
    this.name = 'parent3';
    this.play = [1, 2, 3];
  }
  function Child3() {
    Parent3.call(this);
    this.type = 'child3';
  }
  Child3.prototype = new Parent3(); // 缺点:Parent3.call(this)时,Parent3已经执行了一次,这里Parent3又执行一次
  var s3 = new Child3();
  var s4 = new Child3();
  s3.play.push(4);
  console.log(s3.play, s4.play);

(5)组合方式优化

  /**
   * 组合继承的优化1
   */
  function Parent4() {
    this.name = 'parent4';
    this.play = [1, 2, 3];
  }
  function Child4() {
    Parent4.call(this);
    this.type = 'child4';
  }
  Child4.prototype = Parent4.prototype;
  var s5 = new Child4();
  var s6 = new Child4();
  s5.play.push(4);
  console.log(s5.play, s6.play);
  // 判断s5是谁实例化的实例
  console.log(s5 instanceof Child4, s5 instanceof Parent4); // true true 无法判断
  console.log(s5.__proto__.constructor === Child4, s5.__proto__.constructor ===  Parent4); // false true

  /**
   * 组合继承的优化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
  Child5.prototype.constructor = Child5; // 必要

  var s7 = new Child5();
  console.log(s7 instanceof Child5, s7 instanceof Parent5); // true true 无法判断
  console.log(s7.__proto__.constructor === Child5, s7.__proto__.constructor ===  Parent5); // true false

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值