XXHolic / segment

some notes
MIT License
28 stars 4 forks source link

关于 this 的误解 #40

Open XXHolic opened 5 years ago

XXHolic commented 5 years ago

引子

this 是一个很特别的关键字,它被自动定义在所有的函数作用域中。我们知道 this 是在运行时进行绑定,并不是在编写时绑定,它的上下文取决于函数调用时的各种条件。

this 提供了更优雅的方式来隐性传递一个对象引用,这样可以将 API 设计的更加简洁且易于复用。

对于 this 的理解,有两种常见的误解,下面分别介绍一下。

指向自身

this 字面上的含义,指向函数自身也是说的通。下面先看个例子。

function counter(num) {
  console.info("counter: ",num);

  this.count++;
}

counter.count = 0;

var index;

for (index = 0; index < 5; index++) {
  counter(index);
}

console.info("counter.count: ",counter.count);
点击查看结果 ![38-this-self][url-local-this-self] 打印出来的信息有 5 条,说明 `counter()` 的确调用了 5 次,但 `counter.count` 仍然是 0。说明 `this` 指向自身是错误的。 当遇到这样的问题时候,我们可以很容易的想到可以达到预期结果的方法,例如把 `count` 放到一个新的对象里面 ```javascript function counter(num) { console.info("counter: ",num); data.count++; } var data = { count:0 }; // …………………… console.info("count: ",data.count); ``` 或者显示的引用 `counter`。 ```javascript function counter(num) { console.info("counter: ",num); counter.count++; } counter.count = 0; ``` 但这两种方法都是回避了 `this` 的问题,并不是接受了 this。

指向作用域

this 指向函数的作用域,在某种情况下它是正确的,但是在其他情况下它却是错误的。

需要明确的是,this 在任何情况下都不指向函数的词法作用域。在 JavaScript 内部,作用域确实和对象类似,可见的标识符都是它的属性。但是作用域“对象”无法通过 JavaScript 代码访问,它存在于 JavaScript 引擎内部。看下面的示例。

function bike() {
  var color = 'red';
  this.getColor();
}

function getColor() {
  console.info("car color:",this.color);
}

bike();
点击查看结果 ![38-this-scope][url-local-this-scope] 这段代码试图使用 `this` 连通 `bike()` 和 `getColor()` 的词法作用域,从而让 `getColor()` 可以访问 `bike()` 作用域里的变量 `color`,这是行不通的。 每当想要把 `this` 和词法作用域的查找混合使用时,一定要提醒自己,这是无法实现的。

参考资料