你不知道的JS系列 ( 18) - this 的错误认识

第一种误解:this 理解成指向函数本省,函数看作一个对象,this 并不像我们所想的那样指向函数本身。
function foo(num){
  console.log('foo: ' + num);
  this.count++;
}
foo.count = 0;
var i;
for(i=0; i<10; i++){
  if (i > 5) {
    foo(i);
  }
}
console.log(foo.count); // 0

foo 确实被调用了 4 次,但是 foo.count 仍然是 0.显然从字面意思来理解 this 是错误的。如果我增加的 count 属性和预期不一样,那么增加的是哪个 count?实际上,如果深入探索的话,就会发现这段代码在无意中创建了一个全局变量,它的值是 NaN。那我们如何解决这个问题?

function foo(num){
  console.log('foo: ' + num);

  // 记录 foo 被调用的次数
  data.count++;
}
var data = {
  count: 0
}
var i;
for(i=0; i<10; i++){
  if (i > 5) {
    foo(i);
  }
}
console.log(data.count); // 4

从某种角度来说这个方法确实解决了问题,但可惜它忽略了真正的问题——无法理解 this 的含义和工作原理——而是返回舒适区,使用了一种更熟悉的技术,词法作用域



function foo(num){
  console.log('foo: ' + num);

  // 记录 foo 被调用的次数
  foo.count++;
}
foo.count = 0;
var i;
for(i=0; i<10; i++){
  if (i > 5) {
    foo(i);
  }
}
console.log(foo.count); // 4

然而,这种方法同样回避了 this 的问题,并且依赖于变量 foo 的词法作用域

function foo(num){
  console.log('foo: ' + num);
  this.count++;
}
foo.count = 0;
var i;
for(i=0; i<10; i++){
  if (i > 5) {
    foo.call(foo, i);
  }
}
console.log(foo.count); // 4

这次我们接受了 this,没有回避它。



第二种误解:this 指向函数的作用域。在某种情况下它是正确的,但明确的是,this 在任何情况下都不指向函数的词法作用域。
function foo() {
  var a = 2;
  this.bar();
}
function bar(){
  console.log(this.a);
}
foo(); // undefined

这段代码非常完美的展示了 this 多么容易误导人。首先 this.bar() 来引用 bar() 函数。这是绝对不可能成功的。调用 bar() 最自然的方法是省略前端的 this。此外,开发者试图使用 this 联通 foo() 和 bar() 的词法作用域。每当你想要把 this 和词法作用域的查找混合使用时,一定要提醒自己,这是无法实现的。

学习 this 的第一步是明白 this 既不指向函数自身也不指向函数的词法作用域。
this 是在运行时进行绑定的,并不是在编写时绑定。this 的绑定和函数声明的位置没有任何关系,只取决于函数的调用方式。







原文地址:https://www.cnblogs.com/wzndkj/p/12400209.html