MST

星途 面试题库

面试题:JavaScript 复杂嵌套函数与 this 的指向问题剖析

给定如下代码: ```javascript function outer() { let self = this; function middle() { function inner() { console.log(this === self); } inner(); } middle(); } new outer(); ``` 解释这段代码输出结果的原因,同时假设要让 `inner` 函数中的 `this` 指向 `outer` 函数的实例,在不改变函数调用方式的前提下,应该如何修改代码?
40.8万 热度难度
编程语言JavaScript

知识考点

AI 面试

面试题答案

一键面试

输出结果原因解释

  1. new outer():通过 new 关键字调用 outer 函数,会创建一个新的对象(outer 函数的实例),此时 outer 函数内部的 this 指向这个新创建的实例对象。
  2. let self = this;:将 outer 函数内部的 this(即新创建的实例对象)赋值给 self 变量。
  3. function middle()middle 函数是在 outer 函数内部定义的普通函数,它本身没有自己的 this 绑定(在非严格模式下,默认 this 指向全局对象 window;在严格模式下,thisundefined)。
  4. function inner()inner 函数同样是普通函数,它也没有自己的 this 绑定,在 inner 函数中执行 console.log(this === self); 时,this 指向全局对象 window(非严格模式)或 undefined(严格模式),而 self 指向 outer 函数的实例,所以 this === self 返回 false

修改代码使 inner 函数中的 this 指向 outer 函数的实例

  1. 使用箭头函数:箭头函数没有自己的 this 绑定,它的 this 继承自外层作用域。可以将 inner 函数改为箭头函数:
function outer() {
    let self = this;
    function middle() {
        const inner = () => {
            console.log(this === self);
        };
        inner();
    }
    middle();
}
new outer();

在上述代码中,箭头函数 innerthis 继承自 middle 函数的作用域,而 middle 函数的作用域中 this 虽然不是指向 outer 实例,但箭头函数会沿着作用域链找到 outer 函数作用域中的 this(即 outer 实例),此时 this === self 返回 true

  1. 使用 bind 方法:在调用 inner 函数时,可以使用 bind 方法将 this 绑定到 outer 函数的实例上:
function outer() {
    let self = this;
    function middle() {
        function inner() {
            console.log(this === self);
        }
        inner.bind(this)();
    }
    middle();
}
new outer();

这里 inner.bind(this)() 会创建一个新的函数,并且将这个新函数的 this 绑定到 middle 函数调用时的 this,而 middle 函数在 outer 函数内部调用,outer 函数通过 new 调用,所以 middle 函数调用时的 this 指向 outer 函数的实例,这样在 inner 函数中 this === self 返回 true