JavaScript 中的函数与原型链:一道有趣的面试题

29 阅读3分钟

欢迎来到前端的日常,前端宝典持续更新,目前已经有200+道面试题,更多面试题可以到 前端宝典 进行查看,快来刷题吧~

JavaScript 中的函数与原型链:一道有趣的面试题

在 JavaScript 开发中,函数和原型链是两个非常重要的概念。它们不仅在日常开发中频繁使用,也是面试中常见的考点。
今天,我们就通过一道经典的面试题来深入探讨 JavaScript 中函数与原型链的关系。

image.png

一、题目解析

首先,我们来看这道题目:

function Foo() {
    Foo.a = function() {
        console.log(1);
    };
    this.a = function() {
        console.log(2);
    };
}

Foo.prototype.a = function() {
    console.log(3);
};

Foo.a = function() {
    console.log(4);
};

Foo.a();
let obj = new Foo();
obj.a();
Foo.a();

二、代码逐步解析

1. 定义 Foo 函数

function Foo() {
    Foo.a = function() {
        console.log(1);
    };
    this.a = function() {
        console.log(2);
    };
}
  • • 在 Foo 的构造函数中,我们定义了两个方法:
    • • Foo.a:这是一个静态方法,直接绑定到 Foo 函数上。
    • • this.a:这是一个实例方法,绑定到 Foo 的实例上。

2. 定义 Foo 的原型方法

Foo.prototype.a = function() {
    console.log(3);
};
  • • 这里定义了一个原型方法 a,所有通过 Foo 创建的实例都会继承这个方法。

3. 定义 Foo 的静态方法

Foo.a = function() {
    console.log(4);
};
  • • 这里定义了一个静态方法 a,直接绑定到 Foo 函数上。

4. 调用 Foo.a()

Foo.a();
  • • 这里调用的是 Foo 的静态方法 a,输出 4

5. 创建 Foo 的实例

let obj = new Foo();
  • • 创建了一个 Foo 的实例 obj
  • • 在构造函数中,Foo.a 被重新定义为一个输出 1 的方法。
  • • 同时,this.a 被定义为一个输出 2 的方法。

6. 调用 obj.a()

obj.a();
  • • 这里调用的是 obj 的实例方法 a,输出 2
  • • 实例方法的优先级高于原型链上的方法,因此不会调用 Foo.prototype.a

7. 再次调用 Foo.a()

Foo.a();
  • • 这里调用的是 Foo 的静态方法 a,输出 1
  • • 在构造函数中,Foo.a 被重新定义为一个输出 1 的方法,覆盖了之前的定义。

三、输出结果总结

最终的输出结果是:

4
2
1

四、核心知识点详解

1. 静态方法与实例方法

  • • 静态方法:直接绑定到函数上,可以通过函数名直接调用。
  • • 实例方法:绑定到函数的实例上,可以通过实例调用。

2. 构造函数中的方法定义

  • • 在构造函数中定义的方法会覆盖同名的静态方法或原型方法。
  • • 实例方法的优先级高于原型链上的方法。

3. 原型链的作用

  • • 原型链允许实例继承构造函数的原型方法。
  • • 如果实例上没有定义某个方法,JavaScript 会沿着原型链向上查找。

六、总结

通过这道题目,我们可以深入理解 JavaScript 中函数和原型链的关系。构造函数中的方法定义会影响静态方法和实例方法的行为,而实例方法的优先级高于原型链上的方法。掌握这些知识点,不仅能帮助你在开发中更好地使用 JavaScript,还能在面试中给面试官留下深刻的印象。

如果你觉得这篇文章对你有帮助,欢迎点赞和分享哦!更多技术干货,敬请关注!