返回

面试题深扒JS原理与原型链:一道题搞定面试官

前端

一道面试题就能测出你的JavaScript水平?看似简单,实则不然。这道题不仅考察你对JavaScript基本概念的理解,还考验你对语言底层机制的洞察。一起来看看它到底有何玄机!

题干

已知以下代码:

function Person(name) {
  this.name = name;
}

Person.prototype.sayName = function () {
  console.log(this.name);
};

function Employee(name, department) {
  Person.call(this, name);
  this.department = department;
}

Employee.prototype = new Person(); // 关键代码
Employee.prototype.constructor = Employee;

const employee = new Employee('John', 'Engineering');
employee.sayName(); // "John"

试回答以下问题:

  1. 当调用employee.sayName()时,this指向什么?
  2. Person.prototypeEmployee.prototype有什么区别?
  3. Employee构造函数中,为什么需要调用Person.call(this, name)
  4. Employee.prototype = new Person();这句代码意味着什么?
  5. Employee.prototype.constructor = Employee;这句代码为什么是必要的?

答案解析

1. 当调用employee.sayName()时,this指向什么?

当调用employee.sayName()时,this指向employee对象。这是因为sayName()方法定义在Employee.prototype中,而employeeEmployee的实例。因此,当调用employee.sayName()时,this会自动指向employee对象。

2. Person.prototype和Employee.prototype有什么区别?

Person.prototypePerson函数的原型对象,而Employee.prototypeEmployee函数的原型对象。原型对象是用来保存函数的所有实例共享的属性和方法。

Person.prototypeEmployee.prototype的区别在于:

  • Person.prototype只有sayName()方法,而Employee.prototype除了sayName()方法外,还多了department属性。
  • Employee.prototypeconstructor属性指向Employee函数,而Person.prototypeconstructor属性指向Person函数。

3. 在Employee构造函数中,为什么需要调用Person.call(this, name)?

Employee构造函数中,需要调用Person.call(this, name)来执行Person函数的构造函数。这是因为Employee函数继承了Person函数,因此在创建Employee实例时,需要先执行Person函数的构造函数来初始化name属性。

4. Employee.prototype = new Person();这句代码意味着什么?

Employee.prototype = new Person();这句代码意味着Employee函数的原型对象被重新赋值为一个新的Person实例。这使得Employee函数的原型对象能够继承Person函数原型对象的所有属性和方法。

5. Employee.prototype.constructor = Employee;这句代码为什么是必要的?

Employee.prototype.constructor = Employee;这句代码是必要的,因为它可以确保Employee函数的实例的constructor属性指向Employee函数,而不是Person函数。这对于确保Employee函数的实例能够正确地调用Employee函数的构造函数非常重要。

总结

这道面试题考察了JavaScript中的以下知识点:

  • this的指向
  • 原型(prototype)以及原型链
  • 继承
  • 引用

要解出这道题,需要对这些知识点有深入的理解。希望这篇文章能够帮助您更好地理解JavaScript中的这些关键概念。