MST
星途 面试题库

面试题:JavaScript 箭头函数 this 在复杂继承与闭包场景下的表现

考虑以下复杂的 JavaScript 代码结构: ```javascript function Parent() { this.parentValue = 'parent'; this.getInnerValue = function() { const innerFunction = () => { return this.parentValue; }; return innerFunction; }; } function Child() { Parent.call(this); this.childValue = 'child'; this.getFinalValue = function() { const closureFunction = () => { return this.childValue + ':' + this.getInnerValue()(); }; return closureFunction; }; } const childInstance = new Child(); const finalFunction = childInstance.getFinalValue(); console.log(finalFunction()); ``` 请详细解释代码执行过程中箭头函数 `innerFunction` 和 `closureFunction` 中 `this` 的指向是如何确定的,以及如果将箭头函数替换为普通函数,代码行为会发生怎样的变化及原因。
43.9万 热度难度
编程语言JavaScript

知识考点

AI 面试

面试题答案

一键面试

箭头函数 innerFunctionclosureFunctionthis 的指向确定

  1. innerFunctionthis 的指向
    • 在 JavaScript 中,箭头函数没有自己的 this 绑定。它的 this 是在定义时从其周围的作用域继承而来的。
    • Parent 函数中,innerFunction 定义在 getInnerValue 函数内部。getInnerValue 是作为 Parent 实例的方法被调用,所以此时 this 指向 Parent 实例。
    • 因此,innerFunction 中的 this 继承自 getInnerValue 函数的 this,也就是 Parent 实例,所以 this.parentValue 能正确访问到 Parent 实例的 parentValue 属性。
  2. closureFunctionthis 的指向
    • 同样,closureFunction 是箭头函数,它的 this 也是在定义时从其周围的作用域继承而来。
    • closureFunction 定义在 Child 函数的 getFinalValue 方法内部。getFinalValue 是作为 Child 实例的方法被调用,所以此时 this 指向 Child 实例。
    • 所以,closureFunction 中的 this 继承自 getFinalValue 函数的 this,也就是 Child 实例,因此 this.childValue 能访问到 Child 实例的 childValue 属性,this.getInnerValue()() 也能正确调用 Parent 实例的 getInnerValue 方法并获取 parentValue

将箭头函数替换为普通函数时代码行为的变化及原因

  1. 替换 innerFunction 为普通函数
    • 普通函数有自己的 this 绑定,它的 this 是在调用时确定的(取决于函数的调用方式)。
    • 如果将 innerFunction 改为普通函数:
function Parent() {
    this.parentValue = 'parent';
    this.getInnerValue = function() {
        function innerFunction() {
            return this.parentValue;
        };
        return innerFunction;
    };
}
  • innerFunction 被调用时,它可能不是作为 Parent 实例的方法被调用,所以 this 不会指向 Parent 实例。在严格模式下,this 会是 undefined,在非严格模式下,this 可能指向全局对象(在浏览器环境中是 window),这会导致 this.parentValue 访问不到 Parent 实例的 parentValue 属性,会报错或得到意外结果。
  1. 替换 closureFunction 为普通函数
    • 如果将 closureFunction 改为普通函数:
function Child() {
    Parent.call(this);
    this.childValue = 'child';
    this.getFinalValue = function() {
        function closureFunction() {
            return this.childValue + ':' + this.getInnerValue()();
        };
        return closureFunction;
    };
}
  • closureFunction 被调用时,同样由于普通函数 this 是在调用时确定,它可能不是作为 Child 实例的方法被调用,this 不会指向 Child 实例。在严格模式下,this 会是 undefined,在非严格模式下,this 可能指向全局对象,导致 this.childValuethis.getInnerValue() 都无法正确访问 Child 实例的属性和方法,从而报错或得到意外结果。