本文主要讨论一下JS的做用域和this
关键字。做用域,就是你的方法或者变量可访问的区域,是他们执行的上下文。若是你见过这样的代码:javascript
function someFunc() { var _this = this; something.on("click", function() { console.log(_this); }); };
你就会很好奇为何要用this
赋值给一个变量_this
呢?你看完这篇文章就会清楚这个问题的答案了。java
第一种做用域叫作全局做用域(Global Scope)这很容易定义,若是一个方法、变量是全局做用域的,那么它就能够从任何的地方访问到。在浏览器里,全局做用域就是window
对象。因此,若是你的代码里有:ajax
var x = 9;
你实际上是在给window.x
赋值为9
(在浏览器里运行的时候)。若是你喜欢的话,也能够写成window.x = 9
,固然这不是很必要。全局做用域对象的属性能够在代码的任何地方访问到。浏览器
另外的做用域就只有局部做用域了。在JavaScript里通常就是一个方法内部的做用域。好比:this
function someFunction() { var x = 5; } console.log(x); // undefined
变量x
是在方法内部初始化的,那么就只能在方法内部访问。code
若是你声明了一个变量,并且在声明的时候忘记使用var
关键字。那么,这个变量自动被置为全局变量。好比:对象
function someFunction(){ x = 5; } // 执行一个这个方法,完成x的全局设置 someFunction(); console.log(x); // 5
这是一个很是差的实践。你应该尽可能少的往全局做用域添加属性。这也是为何你会常常看到一些库,好比jQuery会这么干:事件
(function() { var jQuery = {/*所有的方法都在这里*/}; window.jQuery = jQuery; })();
把全有的属性、方法都放在一个方法里。而后马上执行这个方法就会把所有的属性和方法都绑定在了局部做用域里。最后把jQuery
对象绑定到全局做用域,间接的把以前定义的属性和方法都暴露出来方便调用。显然我大量的减小了jQuery的代码,可是这就是jQuery代码如何工做的。ip
因为局部做用域只有经过方法的定义来实现。任何在一个方法内部定义的方法均可以访问外部方法里定义的变量。好比:作用域
function outer() { var x = 5; function inner() { console.log(x); // 5 } inner(); }
可是outer()
方法不能够访问inner()
方法定义的任何变量。
function outer() { var x = 5; function inner() { console.log(x); // 5 var y = 100; } inner(); console.log(y); // undefined }
这很容易理解。可是当咱们试图要探究this
关键字的时候就又变得复杂了。我相信不少人都遇到过这样的问题:
${'myLink'}.on('click', function() { console.log(this); // 指向myLink $.ajax({ // 设置ajax相关 success: function() { console.log(this); // 指向的是全局对象。 ??? } }); });
this
是在方法执行的时候自动赋值的变量。它的值和方法的调用方式有很大的关系。好比:
function foo() { console.log(this); // global object } theApp = {}; theApp.foo = function() { console.log(this); // 指向theApp对象 } var link = doeument.getElementById('myLink'); link.addEventListener('click', function() { console.log(this); // 指向link });
MDN对第三个例子的解释很是到位:
事件的this老是指向出发这个事件的元素对象。好比使用一个通用的事件监听器来处理一系列的有类似事件的元素。当使用addEventListener把一个方法添加到一个元素的事件处理器的时候,这个方法的this值就被改变了。注意,this的值是从调用者里传给方法的。
这么作:$('myLink').on('click', function() {})
意味着link被点击的时候方法就会执行。因为这个方法是处理link的事件的,因此this的值就是这个link元素。
在Ajax请求的success回调方法只是一个普通的方法。因此,当它被调用的时候this指向的是全局对象。任何对象,不是对象方法或者事件的时候会遇到的状况。
上面的缘由也就是你在不少地方看到var _this = this;
或者var that = this;
的缘由。来看一个例子:
$('myLink').on('click', function() { console.log(this); //指向myLink var _this = this; $.ajax({ // ajax设置 success: function() { console.log(this); // 指向全局对象 console.log(_this); // 指向myLink } }); });