简单了解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 相关文章推荐
ExtJs 3.1 XmlTreeLoader Example Error
Feb 09 Javascript
Jquery + Ajax调用webService实例代码(asp.net)
Aug 27 Javascript
jQuery获取地址栏参数插件(模仿C#)
Oct 26 Javascript
js 金额文本框实现代码
Feb 14 Javascript
javascript:文字不间断向左移动的实例代码
Aug 08 Javascript
js验证电话号码与手机支持+86的正则表达式
Jan 23 Javascript
jQuery实现渐变弹出层和弹出菜单的方法
Feb 20 Javascript
jQuery实现图片加载完成后改变图片大小的方法
Mar 29 Javascript
js用类封装pop弹窗组件
Oct 08 Javascript
vue单页应用在页面刷新时保留状态数据的方法
Sep 21 Javascript
详解微信小程序开发聊天室—实时聊天,支持图片预览
May 20 Javascript
JavaScript继承的三种方法实例
May 12 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学习之整理字符串
2011/04/17 PHP
简单的php写入数据库类代码分享
2011/07/26 PHP
PHP实现读取一个1G的文件大小
2013/08/24 PHP
PHP的一个完美GIF等比缩放类,附带去除缩放黑背景
2014/04/01 PHP
一个经典的PHP验证码类分享
2014/11/18 PHP
PHP实现微信小程序人脸识别刷脸登录功能
2018/05/24 PHP
javascript编程起步(第五课)
2007/01/10 Javascript
使弱类型的语言JavaScript变强势
2009/06/22 Javascript
使用ImageMagick进行图片缩放、合成与裁剪(js+python)
2013/09/16 Javascript
如何从jQuery的ajax请求中删除X-Requested-With
2013/12/11 Javascript
jquery制作LED 时钟特效
2015/02/01 Javascript
JavaScript实现仿淘宝商品购买数量的增减效果
2016/01/22 Javascript
jquery判断input值不为空的方法
2016/06/05 Javascript
Node.js+Express+MySql实现用户登录注册功能
2017/07/10 Javascript
Vue结合SignalR实现前后端实时消息同步
2017/09/19 Javascript
微信小程序实现漂亮的弹窗效果
2020/05/26 Javascript
Vue2.0 实现歌手列表滚动及右侧快速入口功能
2018/08/08 Javascript
通过实例了解JS执行上下文运行原理
2020/06/17 Javascript
探究一道价值25k的蚂蚁金服异步串行面试题
2020/08/21 Javascript
axios封装与传参示例详解
2020/10/18 Javascript
jquery实现鼠标悬浮弹出气泡提示框
2020/12/23 jQuery
[02:08:58]2014 DOTA2国际邀请赛中国区预选赛 Ne VS CIS
2014/05/22 DOTA
Python遍历目录的4种方法实例介绍
2015/04/13 Python
Python实现简单的代理服务器
2015/07/25 Python
基于Python中单例模式的几种实现方式及优化详解
2018/01/09 Python
使用 django orm 写 exists 条件过滤实例
2020/05/20 Python
python反爬虫方法的优缺点分析
2020/11/25 Python
学前班教师的自我鉴定
2013/12/05 职场文书
2013年学期结束动员演讲稿
2014/01/07 职场文书
保险经纪人求职信
2014/03/11 职场文书
三年级学生评语
2014/04/23 职场文书
老龄工作先进事迹
2014/08/15 职场文书
农民工预备党员思想汇报
2014/09/14 职场文书
买房子个人收入证明
2014/10/12 职场文书
2015年防灾减灾工作总结
2015/07/24 职场文书
创业计划书之蛋糕店
2019/08/29 职场文书