2020-11-12 | 第1章 关于this

为什么要用this

我理解的this是执行上文的环境,和执行的地方很有关系。this提供了一种更优雅的方式来隐式“传递”一个对象的应用,就像下方的代码,可以把API设计的更加优雅。

function identify() { 
    return this.name.toUpperCase(); 
} 
function speak() { 
    var greeting = "Hello, I'm " + identify.call( this ); 
    console.log( greeting ); 
} 
var me = { 
    name: "Kyle" 
}; 
var you = { 
    name: "Reader" 
};
identify.call( me ); // KYLE 
identify.call( you ); // READER 
speak.call( me ); // Hello, 我是 KYLE 
speak.call( you ); // Hello, 我是 READER

误解

  • This并不是指向函数本身。
function foo(num) { 
    console.log( "foo: " + num ); 
    // 记录 foo 被调用的次数 
    this.count++; 
}
foo.count = 0; 
var i; 
for (i=0; i<10; i++) { 
if (i > 5) { 
    foo( i ); 
} 
}
// foo: 6 
// foo: 7 
// foo: 8 
// foo: 9 
// foo 被调用了多少次? 
console.log( foo.count ); // 0 -- WTF?

这里this.count是在运行的上下文上创建了一个count,这段代码是在window上创建的,和foo.count 不是一个变量。当然我们可以通过存储变量来解决这个问题,但是这样就不知道this的运行背后的原理。

如果我们想要在foo计算运行次数,改进的方式在于调用的时候的时候,请看下方代码:

function foo(num) { 
    console.log( "foo: " + num ); 
    // 记录 foo 被调用的次数 
    // 注意,在当前的调用方式下(参见下方代码),this 确实指向 foo 
    this.count++; 
}
foo.count = 0; 
var i; 
for (i=0; i<10; i++) { 
    if (i > 5) { 
        // 使用 call(..) 可以确保 this 指向函数对象 foo 本身 
        foo.call( foo, i ); 
    } 
}
// foo: 6 
// foo: 7 
// foo: 8 
// foo: 9 
// foo 被调用了多少次? 
console.log( foo.count ); // 4
  • This指向函数作用域,某些请看是对的,其他时候不是正确的
function foo() { 
    var a = 2; 
    this.bar(); 
} 
function bar() { 
    console.log( this.a ); 
}
foo(); // ReferenceError: a is not defined 

这段代码是期望通过this能打通foo和bar的作用域,但是这是无法实现的。

This是在运行时进行绑定的,并不是编写时绑定,它的上下文取决于函数调用时各种条件。

当一个函数被调用时,会创建一个执行上下文,这个记录回包含函数在哪里被调用(调用栈),函数的调用方法,传入的参数等信息。this就是记录的其中一个属性,会在函数执行的过程中用到

小结

  • this 既不指向函数自身也不指向函数的词法作用域
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容