JavaScript的this和作用域

简介:

本文主要讨论一下JS的作用域和this关键字。作用域,就是你的方法或者变量可访问的区域,是他们执行的上下文。如果你见过这样的代码:

function someFunc() {
  var _this = this;
  something.on("click", function() {
    console.log(_this);
  });
};

你就会很好奇为什么要用this赋值给一个变量_this呢?你看完这篇文章就会清楚这个问题的答案了。

第一种作用域叫做全局作用域(Global Scope)这很容易定义,如果一个方法、变量是全局作用域的,那么它就可以从任何的地方访问到。在浏览器里,全局作用域就是window对象。所以,如果你的代码里有:

var x = 9;

你其实是在给window.x赋值为9(在浏览器里运行的时候)。如果你喜欢的话,也可以写成window.x = 9,当然这不是很必要。全局作用域对象的属性可以在代码的任何地方访问到。

另外的作用域就只有局部作用域了。在JavaScript里一般就是一个方法内部的作用域。比如:

function someFunction() {
  var x = 5;
}
console.log(x); // undefined

变量x是在方法内部初始化的,那么就只能在方法内部访问。

一些需要注意的地方

如果你声明了一个变量,而且在声明的时候忘记使用var关键字。那么,这个变量自动被置为全局变量。比如:

function someFunction(){
  x = 5;
}

// 执行一个这个方法,完成x的全局设置
someFunction();

console.log(x); // 5

这是一个非常差的实践。你应该尽量少的往全局作用域添加属性。这也是为什么你会经常看到一些库,比如jQuery会这么干:

(function() {
  var jQuery = {/*全部的方法都在这里*/};
  window.jQuery = jQuery;
})();

把全有的属性、方法都放在一个方法里。然后立刻执行这个方法就会把全部的属性和方法都绑定在了局部作用域里。最后把jQuery对象绑定到全局作用域,间接的把之前定义的属性和方法都暴露出来方便调用。显然我大量的减少了jQuery的代码,但是这就是jQuery代码如何工作的。

由于局部作用域只有通过方法的定义来实现。任何在一个方法内部定义的方法都可以访问外部方法里定义的变量。比如:

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
    }
  });
});

原文地址:https://javascriptplayground.com/javascript-variable-scope-this/













本文转自张昺华-sky博客园博客,原文链接:http://www.cnblogs.com/sunshine-anycall/p/8322322.html,如需转载请自行联系原作者


相关文章
|
20天前
|
存储 JavaScript 前端开发
解释 JavaScript 中的作用域和作用域链的概念。
【4月更文挑战第4天】JavaScript作用域定义了变量和函数的可见范围,静态决定于编码时。每个函数作为对象拥有`scope`属性,关联运行期上下文集合。执行上下文在函数执行时创建,定义执行环境,每次调用函数都会生成独特上下文。作用域链是按层级组织的作用域集合,自内向外查找变量。变量查找遵循从当前执行上下文到全局上下文的顺序,若找不到则抛出异常。
21 6
|
1月前
|
自然语言处理 JavaScript 前端开发
深入理解JS的执行上下文、词法作用域和闭包(中)
深入理解JS的执行上下文、词法作用域和闭包(中)
|
1月前
|
存储 自然语言处理 JavaScript
深入理解JS的执行上下文、词法作用域和闭包(上)
深入理解JS的执行上下文、词法作用域和闭包(上)
|
1月前
|
JavaScript 前端开发
javascript中的this
javascript中的this
|
3月前
|
JavaScript 前端开发
错综复杂的this:理清你的JavaScript代码中的指向问题
错综复杂的this:理清你的JavaScript代码中的指向问题
|
1月前
|
JavaScript
JS中改变this指向的六种方法
JS中改变this指向的六种方法
|
1天前
|
JavaScript 前端开发
js开发:请解释this关键字在JavaScript中的用法。
【4月更文挑战第23天】JavaScript的this关键字根据执行环境指向不同对象:全局中指向全局对象(如window),普通函数中默认指向全局对象,作为方法调用时指向调用对象;构造函数中指向新实例,箭头函数继承所在上下文的this。可通过call、apply、bind方法显式改变this指向。
7 1
|
1月前
|
JavaScript 前端开发
js开发:请解释什么是作用域(scope),并说明全局作用域、局部作用域和块级作用域的区别。
JavaScript中的作用域规定了变量和函数的可见性与生命周期。全局作用域适用于整个脚本,变量可通过全局对象访问,可能导致命名冲突和内存占用。局部作用域限于函数内部,每次调用创建新作用域,执行完毕后销毁。ES6引入的块级作用域通过`let`和`const`实现,变量仅在其代码块内有效,并有暂时性死区。作用域机制有助于代码组织和变量管理。
23 1
|
1月前
|
JavaScript
JS中call()、apply()、bind()改变this指向的原理
JS中call()、apply()、bind()改变this指向的原理
|
1月前
|
JavaScript 前端开发
JS作用域与作用域链
JS作用域与作用域链