学习this关键字(一)

this关键字是JavaScript中最复杂的机制之一。以致于我使用多年也很难说清它到底指向什么,咱们有必要好好学习一下。this也是咱们学习和使用JavaScript中的一座大山,咱们必须翻过这座山。java

为何要使用this

先看一段代码以下:函数

var foo = {
    name:'tom',
    age:'24',
    say:function(){
        console.log('name: ' + this.name + ', age: ' + this.age);
    }
}
foo.say(); //name: tom, age: 24
var bar = {
    name:'cat',
    age:'25'
}
foo.say.call(bar); //name: cat, age: 25
复制代码

这段代码在不一样的上下文对象(foobar)中重复使用了函数say(),不用写不一样版本的函数。若是不使用this那么就须要给函数say()显示传入一个上下文对象。学习

say:function(context){
        console.log('name: ' + context.name + ', age: ' + context.age);
    }
复制代码

this隐式的传递了一个对象的引用,由于咱们能够将通用模块和API方法设计的更加易用和简洁。ui

什么是this

this指向函数自身

在开始工做的时候很容易把this理解成指向函数自身,不过咱们如今来分析下,this是否是指向函数自身。思考下面一段代码:this

function foo(){
    this.name = 'tom';
}
foo.name = 'cat';
foo();
console.log(foo.name); //'cat'
复制代码

最终打印的是cat,显然this不是指向函数自身。执行foo.name=cat,是向对象foo添加一个name属性,可是函数内部代码this.name中的this并非指向那个函数对象。spa

遇到这样的问题,咱们会采用其余的方式来达到目的,好比建立另外一个带有name属性的对象。设计

function foo(){
    obj.name = 'tom';
}
var obj = {
    name:'cat'
}
foo();
console.log(obj.name); //'tom'
复制代码

虽然这种方式确实解决了问题,其使用的是另外一种咱们比较熟悉的技术词法做用域,并无使用this解决。3d

另外一种方法是强制this指向foo函数对象。code

function foo(){
    this.name = 'tom';
}
foo.name = 'cat';
foo.call(foo);
console.log(foo.name);//'tom'
复制代码

此次咱们没有回避this,并且使用call()来帮助咱们使用thiscdn

this指向它的做用域

this的另外一个误区就是,指向函数的做用域。这个问题有点复杂,由于在某种状况下它是正确的,可是在其余状况下它倒是错误的。须要说明的是,this在任何状况下都不指向函数的词法做用域。

javaScript中,做用域确实和对象相似,可见的标识符都是它的属性。可是做用域“对象”没法经过 javaScript代码访问,它存在于javaScript引擎内部。(详细的能够参考以前的文章)

思考下面一段代码:

function foo() { 
    var a = 1;  
    this.bar(); 
}
function bar() { 
    console.log(this.a);
}
foo(); //undefined
复制代码

这段代码看起来像是故意为之,但实则反映出对this的不了解。调用bar()最经常使用的方法是省略前面的this,直接使用词法引用标识符。这段代码还试图经过thisfoo()函数中联动bar()函数访问变量a。这也是不可能的,不能使用this来引用一个词法做用域内部的变量及函数。

this究竟是什么

this是在运行时进行绑定的,并非在编写时绑定,它的上下文取决于函数调用时的各类条件。this 的绑定和函数声明的位置没有任何关系,只取决于函数的调用方式。

当一个函数被调用时,会建立一个执行环境(也叫执行上下文)。执行环境中的活动对象会包含函数在哪里被调用(调用栈)、函数的调用方法、传入的参数等信息。this就是记录的其中一个属性,会在函数执行的过程当中用到。(详细的能够参考以前的文章)

总结

this 其实是在函数被调用时发生的绑定,它指向什么彻底取决于函数在哪里被调用。

参考

相关文章
相关标签/搜索