这份 “谁在说话”(`this`) 说明书准确吗?

结论:**大方向完全正确**——用“我”作比喻,把四条绑定规则 + 箭头函数拆开解释,是目前最容易让初学者秒懂的讲法。下面给出几点**技术层面的补充 / 修正 / 角落案例**,帮助你把这套说辞打磨到“面试官挑不出毛病”。


---


### 1. “默认绑定” 的两个细节

1. **严格模式**

```js

"use strict";

function foo() { console.log(this); }

foo(); // => undefined(不是 window)

```

把这点单独强调一下,能避免同学们在 ESLint 默认 `"use strict"` 的文件里以为自己学错了。


2. **ES Module 顶层**

在 `<script type="module">` 或 `.mjs` 文件的最外层,`this` 直接就是 `undefined`,因为 ES Module 默认是严格模式 + scope 封闭:

```js

console.log(this); // undefined

```


---


### 2. `.bind()` 的“不可逆”与优先级

你用“导演把剧本钉给演员”的比喻形象地说明了 `.bind()` 会返回**新函数**。可以再补一句:

*一旦钉好,后来再用 `.call()` / `.apply()` 都改不了了。*

```js

function foo() { console.log(this.name); }

const obj1 = {name: "A"};

const obj2 = {name: "B"};


const bound = foo.bind(obj1);

bound.call(obj2); // 依旧输出 "A"

```

所以真正的优先级是

`new > bind > call/apply > 隐式 > 默认`

(`new` 最狠,因为即便是 **已 bind 的函数**,在 `new` 时 `this` 仍是新对象;同时 `.bind()` 也能“盖过”隐式)


---


### 3. 箭头函数再加两条防坑线

1. **不能做构造器**

```js

const Foo = () => {};

new Foo(); // TypeError: Foo is not a constructor

```

2. **`call/apply/bind` 对它无效** – 既然它没有自己的 `this`,想改也改不了:

```js

const arrow = () => console.log(this);

arrow.call({x:1}); // 仍是外层的 this,而不是 {x:1}

```


---


### 4. DOM 事件处理里的 `this`

浏览器里再补充一条常用规则:

* 传统写法 `element.onclick = function(){ ... }` —— `this` 指触发事件的元素。

* 若用 **箭头函数** 绑定事件,`this` 就不是元素而是外层作用域;因此很多教程推荐:

```js

element.addEventListener("click", (e) => {

// 用 e.currentTarget 取元素,不要用 this

});

```


---


### 5. Class 语法糖带来的假象

ES6 `class` 其实只是把构造函数 + 原型链包了糖衣,底层仍然走 **new 绑定 / 隐式绑定** 逻辑。提一句可以防止“class 有特殊 this 规则”的误解。

```js

class Person {

constructor(name) { this.name = name; }

say() { console.log(this.name); }

}

```

上例中的 `say()` 跟

```js

Person.prototype.say = function(){ ... }

```

完全一致。


---


### 6. 三个面试级冷门点(了解即可)

1. **`
Function.prototype.call.bind(fn)` 用法**

高阶函数题常出现,但理解了“bind 后再 call 无法改 this”也就通透了。

2. **`super` 调用里的 `this`**

`super.method()` 内部的 `this` 仍指向调用者,而不是 `super` 指向的父类原型。

3. **`new.target`**

判断函数是否通过 `new` 调用的元信息:

```js

function Foo(){

if (!new.target) return new Foo(); // 强制 new

}

```


---


## 终极速记卡(面试背诵版)

```

① new this = 新对象

② bind this = 显式指定(永久)

③ call / apply this = 显式指定(临时)

④ obj.fn() this = obj

⑤ foo() 非严格:window;严格:undefined

★ 箭头函数 没有自己的 this,取词法外层

```


掌握这些边角后,你这份“谁在说话”类比就从**通俗易懂**升级为**覆盖 99% 场景**。剩下 1% 的诡异写法(`with`、`eval`、`Proxy` 里 trap 的 `this`)放在 OJ 里基本碰不到,知道它们存在就够了。


祝讲解更上一层楼。

原文链接:,转发请注明来源!