this在日常javascript编码中很常见, 但是一直以来没有好好总结过。 今天在这里好好总结一下。 本文只讨论浏览器环境。
var name = "window";function foo() {var name = "local";console.log(this.name);}foo();
相信这段代码大家都看到过,在这里this指向了全局,输入结果是"window".一开始我也不理解为什么有些时候this是指向内部函数,有些时候是指向window了。 相信好多小伙伴都和我一样比较疑惑, 后来我去翻阅犀牛书,犀牛书对函数this的解释是:关键字this没有作业域限制, 嵌套的函数不会从调用它的函数中继承this如果函数嵌套作为方法调用其this的值指向调用它的对象。 如果嵌套函数作为函数调用,其this不是全局对象(非严格模式下)就是undefined(严格模式下)。
其实总结一下这段话就是: 一个函数如果是执行而不是作为一个对象的方法来使用,那么它就指向全局对象或者undefined。 所以这就解释了第一段代码。
那接下来我们解释第二个结论:
var name = "window";function foo() {var name = "local";console.log(this.name);}var obj = {name: 'local',foo: foo};obj.foo();
根据上面的结果, 我们很容易得出这里的this就指向了对象obj。在一些称谓中,这个叫做this的隐式绑定。
个人不喜欢文字堆砌,还是直接上代码吧。
var name = "window";var obj = {name: "obj"};function foo() {console.log(this.name);}foo(); //直接调用函数 this指向windowfoo.call(obj); //改变函数的上下文,把obj传进去
这里显式绑定了函数的上下文,让this指向了obj,结果输入为“obj”顺带提一下,call,apply的区别,面试题经常被问。使用call或者apply让一个函数以一个对象的方法执行,第一个参数是指定上下文,可以是一个对象也可以是null。call和apply区别是第二个参数,apply是数组的形式传参。
this的构造函数中使用蛮多的,也蛮方便的。
function Foo() {this.a = "foo";}var f = new Foo();console.log(f.a);
通过new一个函数,那么在构造函数中,this指向实例化的对象f。
上面说完了理论知识,那么我们来几个应用场景题
var name = "window";function foo() {console.log(this.name);}var obj = {name: 'obj',foo: foo};var a = obj.foo;a();obj.foo = null;a();
可能有些同学会认为function也是对象,对象的复制是引用类型复制,那么只是指向obj.foo,如果obj.foo置空了,那么a也就不能输出this.name了。其实结果不是的,函数的复制是值的复制,和数组复制造成引用或者其他的引用不一样。简单点说
a = obj.foo = function { console.log(this.name);}
那么,现在执行a(); 和obj里面的foo函数还没有任何关系了。既两次执行结果都是'window';
看完上面这个例子,同样的我们有些是经常使用回调函数,把函数当一个参数传递,那这个参数是不是也是值的复制?请看下面的例子。
function aaa(fn) {fn();}function foo() {console.log(this.name);}var obj = {name: 'obj',foo: foo};aaa(obj.foo);
如果看不懂这个的话 ,这里也可以简化一下
function aaa(fn) { //在参数这里 可以理解为 var fn = obj.foo;fn(); }
从例子1中我们可以知道函数是值的复制,那必然在aaa里面执行另外一个函数,而不是执行一个函数的方法,结果仍然是'window'.
var name = "window";setTimeout(function(){var name = "local";console.log(this.name);},1000);
相信大家经常用定时器吧,那么有没有踩过这个坑,在定时器中,this是指向全局window的。
因为setTimeout是window下面的方法。代码可以转换为:
var name = "window";window.setTimeout(function(){var name = "local";console.log(this.name);},1000);
一个对象的方法使用,那内部的this是指向这个方法,必然this指向了这个对象本身,既window。
参考文档:
Javascript权威指南第六版
晓婼:http://www.cnblogs.com/xiaoruo/p/4492453.html
新闻热点
疑难解答