JavaScript的this详解

来源:互联网 发布:拉吉普特级驱逐舰知乎 编辑:程序博客网 时间:2024/05/21 11:36

原创声明:本文除了标明引用的内容外,都为本人原创,请尊重本人的知识产权,不能用于商业用途。欢迎转载,转载请在文章开头处插入以下内容:

本文转载自"狂龙ing”的Blog,地址为“http://blog.csdn.net/kuanglong2016/article/details/17395955"

背景知识

很多人初次在JavaScript中使用this时,会感到迷惑,特别是学习过Java/Python语言的人。JavaScript的this与Java中的this以及Python的self作用很类似,但是又有区别,所以很容易造成使用上的的困惑。例如:
function someFunc() {var self = this;//save this in a local variable selfsomething.on("click", function() {console.log(self);});};
很多地方都可以看到类似以上的代码var self = this,看完本问你就明白为什么要这么做了。

概念和原理

要了解this就必须先了解JavaScript中“执行上下文(execution context)”的概念。JavaScript在运行过程中会跟踪和保存多个上下文的栈,当代码运行到一个对象内部时,就把该对象的上下文压栈(实际上,上下文也是一个对象,压栈就是把该上下文对象的“指针”压栈),并执行对象内部的代码,最近进栈的上下文就称为”执行上下文“(参考JavaScript: The Good Parts)。JavaScript执行过程中,this关键字会动态绑定到执行上下文上。
有三种情况可以导致执行上下文的切换(参考Understanding the "this" keyword in JavaScript):
1. 方法调用(method invocation):作为对象属性的函数(function)一般被称为方法(method)
var counter = {  val: 0,  increment: function () {    this.val += 1;  }};counter.increment();console.log(counter.val); // 1counter['increment']();console.log(counter.val); // 2
此时this被绑定到函数所在对象。如果作为普通函数,而不是方法来调用,如下:
var inc = counter.increment;inc();console.log(counter.val); // 2console.log(val); // NaN 
这里inc被赋值为counter的方法,inc实际上是window.inc。因此当调用inc时,this实际上指向的是window。当程序执行到this.val += 1时,执行的代码实际上等价于window.val += 1,但是window.val 是undefined,而undefined + 1 会返回NaN,所以最后打印出NaN。

2. 使用new调用构造函数:
function F (v) {  this.val = v;}var f = new F(“Woohoo!”);console.log(f.val); // Woohoo!console.log(val); // ReferenceError
当使用new来调用构造函数时,this会动态绑定到新生成的对象上。但是如果直接调用该构造函数的话,它跟其他任何普通函数没有任何区别,如下:
var f = F(“Oops!”);console.log(f.val); // undefinedconsole.log(val); // Oops!
此时构造方法作为普通函数来调用,没有生成新的对象,this不变,还是绑定到global对象window上。

3. 使用call或apply:JavaScript中有两个特殊的函数可以手动绑定函数执行的上下文,call和apply,他们会绑定this到第一个参数上。
var add = function (x, y) {      this.val = x + y;    },    obj = {      val: 0    };add.apply(obj, [2, 8]);console.log(obj.val); // 10
call和apply的作用一样,唯一的区别就是提供参数的方式不一样,apply使用数组的方式,call则逐个地列出参数
add.call(obj, 2, 8);console.log(obj.val); // 10

4. 另注:如果是使用eval函数时,规则则会更加复杂,因为我一般不使用eval也不推荐其他人使用eval,所以就不多做介绍。

功能作用:

常见情况:
1.  对象中的匿名函数:
var myObj = {    show: function(){        var help = function(){            console.log("'this' in anonymous is %o", this);        }        help();    }};myObj.show();//'this' in anonymous is Window
因为匿名函数不是myObj的属性,而是Window的属性。因此如果要在匿名函数中得到myObj的引用,则需要临时保存this,如下:
var myObj = {    show: function(){        var self = this;//save this to a local variable self        var help = function(){            console.log("'this' in anonymous is %o", self);        }        help();    }};myObj.show();//'this' in anonymous is Object { show=function()}

2. 事件处理函数:(参考The this keyword)
如果使用如下形式:
element.onclick = doSomething;
此时,doSomething中的this可以动态的绑定到element,因为onclick是element的方法。
如果使用:
<element onclick="doSomething()">
则doSomething是作为一个普通函数直接调用,而不是element的方法,所以doSomething中的this会被绑定到Window。
实际效果如下:
function onclick(){doSomething();}

总结

1. 默认:this = 全局对象
2. 通过对象属性的方式调用方法:this = 该对象
3. 使用new调用构造函数:this = 新对象
4. 使用apply或call:this = apply或call的第一个参数

主要参考文献

1. Understanding the "this" keyword in JavaScript
2. Scope and this in JavaScript
3. The this keyword
4. Understanding "this" in Javascript
5. JavaScript: The Good Parts


0 0
原创粉丝点击