简单了解JavaScript作用域


Posted in Javascript onJuly 31, 2020

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

在 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作用域的资料请关注三水点靠木其它相关文章!

Javascript 相关文章推荐
利用Ext Js生成动态树实例代码
Sep 08 Javascript
jquery全选/全不选/反选另一种实现方法(配合原生js)
Apr 07 Javascript
Javascript代码实现仿实例化类
Apr 03 Javascript
jQuery下拉友情链接美化效果代码分享
Aug 26 Javascript
浅析JavaScript 调试方法和技巧
Oct 22 Javascript
JS对象是否拥有某属性如何判断
Feb 03 Javascript
jQuery分页插件jquery.pagination.js使用方法解析
Feb 09 Javascript
Angular 2 利用Router事件和Title实现动态页面标题的方法
Aug 23 Javascript
vue-devtools的安装步骤
Apr 23 Javascript
vuejs 制作背景淡入淡出切换动画的实例
Sep 01 Javascript
详解如何构建Promise队列实现异步函数顺序执行
Oct 23 Javascript
JQuery特殊效果和链式调用操作示例
May 13 jQuery
基于vue--key值的特殊用处详解
Jul 31 #Javascript
javascript开发实现贪吃蛇游戏
Jul 31 #Javascript
vue 解决无法对未定义的值,空值或基元值设置反应属性报错问题
Jul 31 #Javascript
vscode中Vue别名路径提示的实现
Jul 31 #Javascript
Vue记住滚动条和实现下拉加载的完美方法
Jul 31 #Javascript
vue中渲染对象中属性时显示未定义的解决
Jul 31 #Javascript
JS可断点续传文件上传实现代码解析
Jul 30 #Javascript
You might like
第六节--访问属性和方法
2006/11/16 PHP
PHP输出时间差函数代码
2013/01/28 PHP
解析PHP正则提取或替换img标记属性
2013/06/26 PHP
php下获取http状态的实现代码
2014/05/09 PHP
ThinkPHP连接数据库及主从数据库的设置教程
2014/08/22 PHP
PHP中的流(streams)浅析
2015/07/02 PHP
PHP判断FORM表单或URL参数来的数据是否为整数的方法
2016/03/25 PHP
Javascript 表单之间的数据传递代码
2008/12/04 Javascript
三种取消选中单选框radio的方法
2014/09/09 Javascript
js验证身份证号有效性并提示对应信息
2015/10/19 Javascript
莱鸟介绍window.print()方法
2016/01/06 Javascript
探究Vue.js 2.0新增的虚拟DOM
2016/10/20 Javascript
Javascrip实现文字跳动特效
2016/11/27 Javascript
BootStrap 表单控件之单选按钮水平排列
2017/05/23 Javascript
phantomjs导出html到pdf的方法总结
2017/10/19 Javascript
vue-router动态设置页面title的实例讲解
2018/08/30 Javascript
详解swiper在vue中的应用(以3.0为例)
2018/09/20 Javascript
从0到1搭建Element的后台框架的方法步骤
2019/04/10 Javascript
easyUI使用分页过滤器对数据进行分页操作实例分析
2020/06/01 Javascript
[05:16]《大圣!大圣》——DOTA2新英雄齐天大圣配音李世宏老师专访
2016/12/13 DOTA
wxPython使用系统剪切板的方法
2015/06/16 Python
Python+matplotlib实现计算两个信号的交叉谱密度实例
2018/01/08 Python
Python使用base64模块进行二进制数据编码详解
2018/01/11 Python
python中将一个全部为int的list 转化为str的list方法
2018/04/09 Python
Python 数据处理库 pandas 入门教程基本操作
2018/04/19 Python
Python批量删除只保留最近几天table的代码实例
2019/04/01 Python
PyQt5基本控件使用详解:单选按钮、复选框、下拉框
2019/08/05 Python
简单了解python 生成器 列表推导式 生成器表达式
2019/08/22 Python
python GUI库图形界面开发之PyQt5滑块条控件QSlider详细使用方法与实例
2020/02/28 Python
Pytorch 卷积中的 Input Shape用法
2020/06/29 Python
任意存:BOXFUL
2018/05/21 全球购物
客服服务心得体会
2013/12/30 职场文书
会计专业求职信
2014/08/10 职场文书
乡镇党的群众路线对照检查材料
2014/09/24 职场文书
OpenCV3.3+Python3.6实现图片高斯模糊
2021/05/18 Python
pycharm部署django项目到云服务器的详细流程
2021/06/29 Python