简单了解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 相关文章推荐
javascript下对于事件、事件流、事件触发的顺序随便说说
Jul 17 Javascript
Javascript中匿名函数的多种调用方式总结
Dec 06 Javascript
jQuery使用ajaxSubmit()提交表单示例
Apr 04 Javascript
JS实现向表格行添加新单元格的方法
Mar 30 Javascript
js+html5实现canvas绘制圆形图案的方法
Jun 05 Javascript
jQuery实现带动画效果的多级下拉菜单代码
Sep 08 Javascript
jQuery实现点击弹出背景变暗遮罩效果实例代码
Jun 24 Javascript
angular+bootstrap的双向数据绑定实例
Mar 03 Javascript
axios发送post请求springMVC接收不到参数的解决方法
Mar 05 Javascript
JS 实现分页打印功能
May 16 Javascript
JS+CSS实现3D切割轮播图
Mar 21 Javascript
js正则表达式简单校验方法
Jan 03 Javascript
基于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
php读取文件内容的三种可行方法示例介绍
2014/02/08 PHP
php判断页面是否是微信打开的示例(微信打开网页)
2014/04/25 PHP
PHP面向对象继承用法详解(优化与减少代码重复)
2016/12/02 PHP
不一样的文字闪烁 轮番闪烁
2009/11/11 Javascript
JavaScript生成GUID的多种算法小结
2013/08/18 Javascript
JQuery结合CSS操作打印样式的方法
2013/12/24 Javascript
jquery实现的判断倒计时是否结束代码
2016/02/05 Javascript
不定义JQuery插件 不要说会JQuery
2016/03/07 Javascript
详解AngularJS控制器的使用
2016/03/09 Javascript
微信小程序 教程之数据绑定
2016/10/18 Javascript
JavaScript实现清空(重置)文件类型INPUT元素值的方法
2016/11/17 Javascript
jQuery Easyui datagrid editor为combobox时指定数据源实例
2016/12/19 Javascript
Bootstrap Scrollspy源码学习
2017/03/02 Javascript
javascript中json对象json数组json字符串互转及取值方法
2017/04/19 Javascript
nuxt+axios解决前后端分离SSR的示例代码
2017/10/24 Javascript
简单明了区分escape、encodeURI和encodeURIComponent
2018/05/26 Javascript
详解Nuxt.js部署及踩过的坑
2018/08/07 Javascript
Vue 莹石摄像头直播视频实例代码
2018/08/31 Javascript
Linux上安装Python的PIL和Pillow库处理图片的实例教程
2016/06/23 Python
实用自动化运维Python脚本分享
2018/06/04 Python
解决pandas使用read_csv()读取文件遇到的问题
2018/06/15 Python
selenium+python环境配置教程详解
2019/05/28 Python
python字典setdefault方法和get方法使用实例
2019/12/25 Python
Django Admin 上传文件到七牛云的示例代码
2020/06/20 Python
如何通过python实现IOU计算代码实例
2020/11/02 Python
html5指南-3.如何实现html元素拖拽功能
2013/01/07 HTML / CSS
HTML5 贪吃蛇游戏实现思路及源代码
2013/09/03 HTML / CSS
Missguided美国官网:英国时尚品牌
2018/01/18 全球购物
毕业生幼师求职自荐信
2013/10/01 职场文书
《梅兰芳学艺》教学反思
2014/02/24 职场文书
金融管理毕业生求职信
2014/03/03 职场文书
工作经常出错的检讨书
2014/09/13 职场文书
医院科室评语
2015/01/04 职场文书
遗嘱继承权公证书
2015/01/26 职场文书
党校团干班培训心得体会
2016/01/06 职场文书
JavaScript实现简单计时器
2021/06/22 Javascript