简单了解JavaScript作用域

所属分类: 网络编程 / JavaScript 阅读数: 1942
收藏 0 赞 0 分享

作用域通常是指在指定的时间内,变量存在于一段代码中。缺乏对作用域的理解可能会导致令人沮丧的调试体验。作用域的概念是关于我们的代码中可以访问到哪些确定的函数或变量,代码的上下文和执行环境。

在 JavaScript 中,有两种类型的作用域:全局和局部作用域。

全局作用域

第一种作用域是全局作用域。它很容易定义。如果一个变量或函数是_全局的_,那么在程序中的任何地方都可以访问到它们。在浏览器中,全局作用域是 window对象。如果在函数外面声明一个变量,那么这个变量就存在全局对象中。例如:

var x = 9;

一旦该变量被定义,则可以被引用为 window.x,因为它存在于全局对象中,我们可以简单的引用它为 x。

局部作用域

JavaScript 也可以在每个函数体中创建局部作用域。例如:

function myFunc() {
  var x = 5;
}

myFunc();

console.log( x ); // ReferenceError: x is not defined

由于 x 是在 myFunc() 中初始化,所以它只能在 myFunc() 中被访问,如果我们试图在 myFunc() 外面访问 x,则会得到一个引用错误。

注意

如果你忘记使用 var 关键字声明变量,那么这个变量会自动变成全局变量。所以这段代码可以运行:

function myFunc() {
  x = 5;
}

myFunc();

console.log( x ); // 5

这是一个坏主意。全局变量的值可以被程序的任何部分或者其他脚本更改。这是不期望发生的,因为它会导致无法预料的副作用。

立即调用表达式(IIFE)提供了一个避免全局变量的方式。你会看到许多如 jQuery 的 JavaScript 库经常使用这种方式:

(function() {
  var jQuery = { /* All my methods go here. */ };
  window.jQuery = jQuery;
})();

将一切包含在一个函数中并立即调用这个函数,这意味着函数中的所有变量都被绑定在_局部作用域_中。在函数结尾部分,你可以通过将 jQuery 对象绑定在全局对象 window 上,将一些方法和属性公开出来。了解更多关于立即调用函数表达式,请查看 Ben Alman 的文章 Immediately-Invoked Function Expression

因为局部作用域通过函数而工作,任何在另一个函数中定义的函数都可以访问外部函数里的变量:

function outer() {
  var x = 5;

  function inner() {
    console.log( x );
  }

  inner(); // 5
}

但是 .outer() 函数不能访问 .inner() 函数中定义的任何变量。

function outer() {
  var x = 5;

  function inner() {
    console.log( x );
    var y = 10;
  }

  inner(); // 5

  console.log( y ); // ReferenceError: y is not defined
}

另外,在一个函数中没有使用 var 关键字定义的变量不是这个函数的局部变量 - JavaScript 会向上遍历作用域链(最后会到 window 对象)寻找之前定义的这个变量。如果这个变量没有定义,则会在全局中定义该变量,这样会导致意外的结果。

// Functions have access to variables defined in the same scope.

var foo = "hello";

var sayHello = function() {
  console.log( foo );
};

sayHello(); // "hello"

console.log( foo ); // "hello"

相同名称的变量可以在不同作用域中保存不同的值:

var foo = "world";

var sayHello = function() {
  var foo = "hello";
  console.log( foo );
};

sayHello(); // "hello"

console.log( foo ); // "world"

当在一个函数中引用一个外部作用域定义的变量,函数可以访问在该函数定义之后发生改变的变量值。

var myFunction = function() {
  var foo = "hello";
  var myFn = function() {
    console.log( foo );
  };
  foo = "world";
  return myFn;
};

var f = myFunction();

f(); // "world"

这是一个更复杂的作用域例子:

(function() {

  var baz = 1;

  var bim = function() {
    console.log( baz );
  };

  bar = function() {
    console.log( baz );
  };

})();

在这个实例中,运行:

console.log( baz ); // baz is not defined outside of the function

将会得到一个 ReferenceError。baz 仅仅是在函数中定义,并且没有暴露在全局作用域中。

bar(); // 1

.bar() 是在匿名函数中定义的, 但是它没有使用 var 关键字定义,这意味着它没有绑定到局部作用域,而是在全局作用域创建。另外,它可以访问 baz 变量,因为 .bar() 是在与 baz 相同的作用域定义的,所以它可以访问变量 baz,即使函数外部的其他代码不可以。

bim(); // ReferenceError: bim is not defined

.bim() 只在函数中定义的,所以它作为局部变量而不存在于全局对象中。

以上就是简单了解JavaScript作用域的详细内容,更多关于JavaScript作用域的资料请关注脚本之家其它相关文章!

更多精彩内容其他人还在看

深入解析Vue 组件命名那些事

本篇文章主要介绍了深入解析Vue 组件命名那些事,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享

Vue学习笔记进阶篇之vue-cli安装及介绍

这篇文章主要介绍了Vue学习笔记进阶篇之vue-cli安装及介绍,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

jquery版轮播图效果和extend扩展

这篇文章主要为大家详细介绍了jquery版轮播图效果,以及extend扩展的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

jQuery Validate格式验证功能实例代码(包括重名验证)

本文通过实例代码给大家介绍了jQuery Validate格式验证功能,代码中包括重名验证的方法,需要的的朋友参考下吧
收藏 0 赞 0 分享

Angular.js中angular-ui-router的简单实践

本篇文章主要介绍了Angular.js中angular-ui-router的简单实践,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

JavaScript实现二维坐标点排序效果

这篇文章主要为大家详细介绍了JavaScript实现二维坐标点排序效果,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

深入理解vue2.0路由如何配置问题

本篇文章主要介绍了vue2.0路由配置问题,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享

基于bootstrap实现多个下拉框同时搜索功能

这篇文章主要为大家详细介绍了基于bootstrap实现多个下拉框同时搜索功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

JavaScript 值类型和引用类型的初次研究(推荐)

这篇文章主要介绍了JavaScript 值类型和引用类型的初次研究,需要的朋友可以参考下
收藏 0 赞 0 分享

利用jQuery异步上传文件的插件用法详解

这篇文章主要介绍了利用jQuery异步上传文件的插件用法详解,需要的朋友可以参考下
收藏 0 赞 0 分享
查看更多