react闲谈——JavaScript语法this全解
先玩一个小游戏,你能回答下面的问题吗? <script type="text/javascript"> foo = "bar"; function testThis() { foo = "foo"; } console.log(this.foo); //第一个this.foo是什么? testThis(); console.log(this.foo); //第二个this.foo又是什么? </script> 进入正题,如果你学过其他编程语言,你就知道this不只是JavaScript独有的东西。 一、全局作用域下的this this === window 二、函数作用域下的this 1、函数直接调用的情况 非严格模式下,直接调用函数,内部的this将指向window。 t = 10 //定义一个全局变量t function test(){ return this.t; } console.log(test()) // 10 严格模式下,直接调用函数,内部的this将指向该函数运行时的环境。 function test(){ "user strict" //严格模式 return this; } console.log(test()) //undefined 这个例子中,虽然函数是在window下面直接运行的,但是他没有被调用,而是直接运行,所以this是undefined。 function test(){ "user strict" //严格模式 return this; } console.log(window.test()) //window 使用了window来调用函数,那么,函数的执行环境就是window,所以函数内部的this === window。当然,这已经不属于函数直接调用的情况了。 (function test(){ //"use strict"; 严格模式下this指向undefined var t = 9; console.log(this) // window })() 无论是自执行还是直接调用函数,都是一样的,他没有“被调用”,所以就没有上下文环境。那么为什么非严格模式下面,会指向window呢,是不是说明非严格模式下默认指向window.test()?没错,但严格模式下就没有默认的说法了,严格模式下也没法给自执行函数指定window是不。 2、对象中的this。 当用对象调用自己里面定义的方法时,this指向的这个对象。 var obj = { id: 9,test: function() { return this.id; } }; console.log(obj.test()); //9 这个例子中,test()是对象obj里面的方法,通过obj调用test方法obj.test(),那么该函数的运行环境就是obj所在的上下文,所以this指向obj。 接着就是匿名函数的调用,this又指向什么? var obj = {id: 9}; function test() { return this.prop; } obj.t = test; console.log(obj.t()); // logs 9 仍然输出obj的id9,这说明this始终与执行环境有关,这里的执行环境就是obj。 3、原型链中的this(属于对象例子的衍生) var o = { f : function(){ return this.a + this.b; } }; var p = Object.create(o); p.a = 1; p.b = 4; console.log(p.f()); // 5 首先定义一个对象o,对象里面有一个函数f,f里面有this,在对象o没有被调用的时候,f里面的this是没有意义的。 var o = { f : function(){ return this.a + this.b; } }; o.a = 1,o.b = 4 => var o = { a: 1,b: 4,f : function(){ return this.a + this.b; } }; => o.f() // 5 4、getter与setter中的this(属于对象例子的衍生) var obj = { a: 1,b: 2,get test(){ return this.a + this.b; },set f(x) { this.a = x; this.b = x + 1; } }; console.log(obj.test) //3 obj.f = 5 console.log(obj.test) //11 在上面的例子中,定义一个对象obj,有一个get,用来获取this.a + this.b的和,同理,单独一个对象中this是没有意义的,当obj调用它自身的test方法时obj.test,this就指向obj,因为obj是test的运行环境。 5、构造函数中的this function Templete(){ this.a = 8; } var t = new Templete(); console.log(t.a); // 8 上面的例子中,有一个构造函数Templete,当new了一个新的对象t,那么this就指向了t,所以this.a == 8。 6、call和apply中的this function add(x) { return this.a + x } var obj = { a: 10 } var sum = add.call(obj,8) //var sum = add.apply(obj,[8]) console.log(sum) // 18 上面的例子中,我们定义了一个函数add,用来求a+x的和,但是这个a是用this.a指代的,我们如果直接运行add(x),无法给a设置值,这个时候就得apply和call登场了。 7、bind中的this function f(x){ return this.a + x; } var obj = { a: 10 } var sum = f.bind(obj,8); console.log(sum()) // 18 还是第6种情况中的例子,只不过用bind来绑定当前函数的this指向obj,这里就不需要再重复解释一遍了。 8、DOM事件函数中的this var ele = document.getElementById('tab'); ele.addEventListener('click',func,false); function func(e) { console.log(this === e.target) //true } 这个例子中,给id叫做tab的元素绑定了click事件,事件名称叫做func,那么使得func()函数执行的环境是ele,所以func()函数中的this是指向ele元素。 9、内联事件中的this。 <div onclick="alert(this.tagName.toLowerCase())"></div> 打印出来是当前的div元素。 官方还举了一个特殊的例子,看下面。 <button onclick="alert((function(){return this})());"> Show inner this </button> 在这个特殊的例子中,alert里面是一个自执行函数,还记得我在第1种情况说的话吗?自执行函数没有被调用,所以严格模式下this是指向undefined的,而非严格模式下是指向window。 总结:这么多this的场景,其实它就一句话:this永远指向它执行的上下文环境。 说了这么多ES5的this,记住,是浏览器端的,别拿服务端的this来说话。 小试牛刀:学了这么多,累不累,不知道自己学懂没有,做题目测试一下吧。 function Thing1() {} Thing1.prototype.foo = "thing1"; Thing1.prototype.logFoo = function () { console.log(this.foo); } function Thing2() { this.foo = "thing2"; } Thing2.prototype = new Thing1(); var thing = new Thing2(); thing.logFoo(); 题目2: function Thing() {} Thing.prototype.foo = "bar"; Thing.prototype.logFoo = function () { console.log(this.foo); } function doIt(method) { method(); } var thing = new Thing(); thing.logFoo(); doIt(thing.logFoo); 题目3: var obj = { foo: "bar",deeper: { logFoo: function () { console.log(this.foo); } } }; obj.deeper.logFoo(); 题目4: <div class="foo bar1"></div> <div class="foo bar2"></div> <script type="text/javascript"> $(".foo").each(function () { console.log(this); }); $(".foo").each(function () { this.click(); }); </script> 如果你觉得有说的不对的地方,可以指出来,觉得说的好,收藏一下呗。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |