JavaScript原型链与继承|记一次面试经历

前言

这篇文章里面记录了我一次面试Node.js后端开发岗位时,二面的面试官问个人关于JavaScript原型链方面的知识,当面手写代码😱。javascript

但愿这篇文章能对今年要找web前端后者Node.js后端开发工做的同窗有所帮助。前端

必备概念

prototype:不管何时,只要建立了一个新的函数,就会根据一个特定的规则为该函数建立一个prototype属性,只有函数才有prototype属性。java

proto:全部对象都包含一个__proto__属性指向它的构造函数的prototypeweb

constructor:全部对象都包含constructor属性,这个属性包含一个指向prototype属性所在函数的指针。面试

场景再现

二面那天下着大雨🌧,面试的时间约的是早上的9:30。半身湿透的我在hr的带领下来到了会议室,不一会进来了一个年龄大约40岁的人,手里拿了几张白纸。编程

在我进行完必备的礼仪后,他也作了简单的介绍(部门经理)。后端

....bash

他问:你带笔了吗?app

我说:带了。函数

他说:这几张纸你拿着,一会要写代码,轻松点,咱们开始吧~

衣服湿的太多,当时确实有点冷🥶

请模拟实现new操做符

这道题考察的是使用new操做符调用构造函数所经历的阶段:

  1. 建立一个新的对象;
  2. 将构造函数的做用域赋给新的对象;
  3. 执行构造函数中的代码;
  4. 返回新的对象;
function analog_new(constructor, ...rest) {
    if (typeof constructor !== 'function') {
        return constructor;
    }
    //建立新的对象,关联构造函数的原型对象
    const _constructor = Object.create(constructor.prototype);
    //执行构造函数
    const obj = constructor.apply(_constructor, rest);
    //若是构造函数执行结果是对象则返回执行结果
    if (typeof obj === 'object') {
        return obj;
    } else {
        return _constructor;
    }
 };
复制代码

什么是继承

继承、封装、多态是面向对象编程的基本特性。经过继承子类不只能够具备父类的方法和属性还能够加入新的属性和方法或者修改父类的属性和方法。

官方描述: 继承是面向对象的编程的一种基本特性。 借助继承,可以定义可重用(继承)、扩展或修改父类行为的子类。 成员被继承的类称为基类。 继承基类成员的类称为派生类。

js如何实现继承

经过原型链能够实现继承。

js实现继承有哪些方式

  1. 借用构造函数
  2. 原型链
  3. 组合继承

请写出来

这里面借用构造函数实现继承原型链继承当时并无问我缺点,是我在写文章的时候加上去的。

借用构造函数实现继承

function Animal(type) {
    this.type = type;
 }

 function Duck() {
    //继承Animal
    Animal.call(this,'duck');
 }

 const duck = new Duck();
 console.log(duck.type);//duck
复制代码

缺点:不能继承Animal原型链上的属性

function Animal(type) {
    this.type = type;
 }

 Animal.prototype.walk = function (){
    console.log('walk');
 }

 function Duck() {
    //继承Animal
    Animal.call(this,'duck');
 }

  const duck = new Duck();
  console.log(duck.type);//duck
  duck.walk();//Error:duck.walk is not a function
复制代码

原型链继承

function Animal(type) {
     this.type = type;
 }
 Animal.prototype.walk = function () {
     console.log('walk...');
 }

 function Duck() { }
 Duck.prototype = new Animal('duck');//将Duck的原型对象赋值为Animal的实例实现继承

 const duck = new Duck();
 console.log(duck.type);//duck
 duck.walk();//walk...
复制代码

缺点:当某一个实例修改原型链上某一个属性时,若是实例类型是引用类型,那么其它实例的属性也会被修改。

function Animal(type) {
    this.type = type;
    this.colors = ['yellow'];
 }
 Animal.prototype.walk = function () {
    console.log('walk...');
 }

 function Duck() { }
 Duck.prototype = new Animal('duck');//将Duck的原型对象赋值为Animal的实例实现继承


 const normal_duck = new Duck();//正常的鸭子
 const variation_duck = new Duck();//变异的鸭子
 variation_duck.colors.push('black');//变异的鸭子有yellow和black两种颜色

 //修改variation_duck对象的color属性,normal_duck对象的color属性也发生了变化
 console.log(normal_duck.colors);//[ 'yellow', 'black' ]
 console.log(variation_duck.colors);//[ 'yellow', 'black' ]
复制代码

组合继承

function Animal(type) {
    this.type = type;
    this.color = ['yellow'];
 }
 Animal.prototype.walk = function () {
    console.log('walk...');
 }

 function Duck() {
    Animal.call(this, 'duck');
 }
 Duck.prototype = Object.create(Animal.prototype);
 Duck.prototype.constructor = Duck;

 const normal_duck = new Duck();//正常的鸭子
 const variation_duck = new Duck();//变异的鸭子
 variation_duck.color.push('black');//变异的鸭子有yellow和black两种颜色

 //修改variation_duck对象的color属性,normal_duck对象的color属性未发生了变化
 console.log(normal_duck.color);//[ 'yellow' ]
 console.log(variation_duck.color);//[ 'yellow', 'black' ]
复制代码

总结

说实在的第一次遇到当面手写代码仍是有些紧张。这种状况应该比较少吧!后面还写了其它的一些和原型链无关的知识,这里就不写了。可是在后面相似这样的互动比较多:面试官让你手写一段代码,而后在提出问题不断的这样反复...

通过近两个小时的鏖战,最终HR找我谈了薪资。

这个分享一下我的经验:

  1. 在保证答题速度的前提下,必定要注意字迹的工整。
  2. 代码命名必定要规范,尽可能把本身知道的都写/说出来。
  3. 在沟通的过程当中保持使用双手将纸递给面试官。

最后最各位2020都能找到有本身喜欢的工做。❤❤❤

参考

<<javascript高级程序设计>>
C# 继承

相关文章
相关标签/搜索