轻松5句话解决JavaScript的作用域


Posted in Javascript onJuly 15, 2016

javascript 程序的每一个字节都是在这个或那个运行上下文(execution context)中执行的。你可以把这些上下文想象为代码的邻居,它们可以给每一行代码指明:从何处来,朋友和邻居又是谁。没错,这是很重要的信息,因为 javascript社会有相当严格的规则,规定谁可以跟谁交往。运行上下文则是有大门把守的社区而非其内开放的小门。

我们通常可以把这些社会边界称为作用域,并且有充足的重要性在每一位邻居的宪章里立法,而这个宪章就是我们要说的上下文的作用域链(scope chain)。在特定的邻里关系内,代码只能访问它的作用域链内的变量。与超出它邻里的变量比起来,代码更喜欢跟本地(local,即局部)的打交道。

任何程序设计语言都有作用域的概念,简单的说,作用域就是变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期。JavaScript的作用域一直以来是前端开发中比较难以理解的知识点,对于JavaScript的作用域主要记住几句话,轻松搞定JavaScript作用域

一、“JavaScript中无块级作用域”

在Java或C#中存在块级作用域,即:大括号也是一个作用域。

public static void main ()
{ if(1==1){
 String name = "seven";
 }
 System.out.println(name);
}// 报错
public static void Main()
{ if(1==1){
 string name = "seven";
 }
 Console.WriteLine(name);
}// 报错

在JavaScript语言中无块级作用域

function Main(){
 if(1==1){
 var name = 'seven';
 }
 console.log(name);
}// 输出: seven

二、JavaScript采用函数作用域

在JavaScript中每个函数作为一个作用域,在外部无法访问内部作用域中的变量。

function Main(){
 var innerValue = 'seven';
}
 
Main();
 
console.log(innerValue);
 
// 报错:Uncaught ReferenceError: innerValue is not defined

三、JavaScript的作用域链

由于JavaScript中的每个函数作为一个作用域,如果出现函数嵌套函数,则就会出现作用域链。

xo = 'alex';
 
function Func(){
 var xo = "seven";
 function inner(){
 var xo = 'alvin';
 console.log(xo);
 }
 inner();
}
Func();

如上述代码则出现三个作用域组成的作用域链,如果出现作用域链后,那么寻找变量时候就会出现顺序,对于上述实例:

当执行console.log(xo)时,其寻找顺序为根据作用域链从内到外的优先级寻找,如果内层没有就逐步向上找,直到没找到抛出异常。

轻松5句话解决JavaScript的作用域

四、JavaScript的作用域链执行前已创建

JavaScript的作用域在被执行之前已经创建,日后再去执行时只需要按照作用域链去寻找即可。

示例一:

xo = 'alex';
 
function Func(){
 var xo = "seven";
 function inner(){
 
 console.log(xo);
 }
 return inner;
}
 
var ret = Func();
ret();
// 输出结果: seven

上述代码,在函数被调用之前作用域链已经存在:

全局作用域 -> Func函数作用域 -> inner函数作用域
当执行【ret();】时,由于其代指的是inner函数,此函数的作用域链在执行之前已经被定义为:全局作用域 -> Func函数作用域 -> inner函数作用域,所以,在执行【ret();】时,会根据已经存在的作用域链去寻找变量。

示例二:

xo = 'alex';
 
function Func(){
 var xo = "eirc";
 function inner(){
 
 console.log(xo);
 }
 xo = 'seven';
 return inner;
}
 
var ret = Func();
ret();
// 输出结果: seven

上述代码和示例一的目的相同,也是强调在函数被调用之前作用域链已经存在:

全局作用域 -> Func函数作用域 -> inner函数作用域
不同的时,在执行【var ret = Func();】时,Func作用域中的xo变量的值已经由 “eric” 被重置为 “seven”,所以之后再执行【ret();】时,就只能找到“seven”。

示例三:

xo = 'alex';
function Bar(){
 console.log(xo);
}
 
function Func(){
 var xo = "seven";
 
 return Bar;
}
 
var ret = Func();
ret();
// 输出结果: alex

上述代码,在函数被执行之前已经创建了两条作用域链:

全局作用域 -> Bar函数作用域
全局作用域 -> Func函数作用域
当执行【ret();】时,ret代指的Bar函数,而Bar函数的作用域链已经存在:全局作用域 -> Bar函数作用域,所以,执行时会根据已经存在的作用域链去寻找。

五、声明提前

在JavaScript中如果不创建变量,直接去使用,则报错:

console.log(xxoo);
// 报错:Uncaught ReferenceError: xxoo is not defined

JavaScript中如果创建值而不赋值,则该值为 undefined,如:

var xxoo;
console.log(xxoo);
// 输出:undefined
在函数内如果这么写:
function Foo(){
 console.log(xo);
 var xo = 'seven';
}
 
Foo();
// 输出:undefined

上述代码,不报错而是输出 undefined,其原因是:JavaScript的函数在被执行之前,会将其中的变量全部声明,而不赋值。所以,相当于上述实例中,函数在“预编译”时,已经执行了var xo;所以上述代码中输出的是undefined。

Js是一门很有趣的语言,由于它的很多特性是针对HTML中DOM的操作,因而显得随意而略失严谨,但随着前端的不断繁荣发展和Node的兴起,Js已经不再是"toy language"或是jQuery时代的"CSS扩展",本文提到的这些无论是对新手还是从传统Web开发中过度过来的Js开发人员来说,都很容易被混淆或误解,希望本文可以有所帮助。

Javascript 相关文章推荐
Extjs学习笔记之一 初识Extjs之MessageBox
Jan 07 Javascript
jQuery建立一个按字母顺序排列的友好页面索引(兼容IE6/7/8)
Feb 26 Javascript
由点击页面其它地方隐藏div所想到的jQuery的delegate
Aug 29 Javascript
Jquery模仿Baidu、Google搜索时自动补充搜索结果提示
Dec 26 Javascript
jQuery实现左右切换焦点图
Apr 03 Javascript
jQuery基于扩展实现的倒计时效果
May 14 Javascript
jQuery中Ajax全局事件引用方式及各个事件(全局/局部)执行顺序
Jun 02 Javascript
js实现返回顶部效果
Mar 10 Javascript
JS获取鼠标位置距浏览器窗口距离的方法示例
Apr 11 Javascript
详解Node.js项目APM监控之New Relic
May 12 Javascript
Angular实现的简单查询天气预报功能示例
Dec 27 Javascript
针对Vue路由history模式下Nginx后台配置操作
Oct 22 Javascript
jQuery EasyUI基础教程之EasyUI常用组件(推荐)
Jul 15 #Javascript
IE下JS保存图片的简单实例
Jul 15 #Javascript
jQuery 3.0中存在问题及解决办法
Jul 15 #Javascript
JavaScript6 let 新语法优势介绍
Jul 15 #Javascript
简单实现轮播图效果的实例
Jul 15 #Javascript
浅谈javascript运算符——条件,逗号,赋值,()和void运算符
Jul 15 #Javascript
JavaScript计算器网页版实现代码分享
Jul 15 #Javascript
You might like
PHP变量内存分配问题记录整理
2013/11/27 PHP
PHP递归删除目录几个代码实例
2014/04/21 PHP
PHP+MySQL修改记录的方法
2015/01/21 PHP
PHP使用XMLWriter读写xml文件操作详解
2018/07/31 PHP
js浮点数精确计算(加、减、乘、除)
2013/12/26 Javascript
浅谈javascript 归并方法
2015/01/21 Javascript
js发送短信倒计时的简单实现方法
2016/09/08 Javascript
微信小程序  Mustache语法详细介绍
2016/10/27 Javascript
AngularJS学习第一篇 AngularJS基础知识
2017/02/13 Javascript
Bootstrap栅格系统使用方法及页面调整变形的解决方法
2017/03/10 Javascript
socket.io学习教程之深入学习篇(三)
2017/04/29 Javascript
vue-cli项目配置多环境的详细操作过程
2018/10/30 Javascript
vue打包之后生成一个配置文件修改接口的方法
2018/12/09 Javascript
layer弹出层显示在top顶层的方法
2019/09/11 Javascript
微信小程序表单验证WxValidate的使用
2019/11/27 Javascript
Auto.JS实现抖音刷宝等刷视频app,自动点赞,自动滑屏,自动切换视频功能
2020/05/08 Javascript
原生JavaScript实现幻灯片效果
2021/02/19 Javascript
Python实现希尔排序算法的原理与用法实例分析
2017/11/23 Python
Python星号*与**用法分析
2018/02/02 Python
Python3.7实现中控考勤机自动连接
2018/08/28 Python
python Pexpect 实现输密码 scp 拷贝的方法
2019/01/03 Python
python下PyGame的下载与安装过程及遇到问题
2019/08/04 Python
程序员的七夕用30行代码让Python化身表白神器
2019/08/07 Python
django 自定义过滤器(filter)处理较为复杂的变量方法
2019/08/12 Python
Python利用全连接神经网络求解MNIST问题详解
2020/01/14 Python
python opencv 实现对图像边缘扩充
2020/01/19 Python
Python cookie的保存与读取、SSL讲解
2020/02/17 Python
基于plt.title无法显示中文的快速解决
2020/05/16 Python
Python远程linux执行命令实现
2020/11/11 Python
积极分子思想汇报
2014/01/04 职场文书
企业晚会策划方案
2014/05/29 职场文书
讲文明懂礼貌演讲稿
2014/09/11 职场文书
社区低保工作总结2015
2015/07/23 职场文书
2015年机关作风和效能建设工作总结
2015/07/23 职场文书
同学联谊会邀请函
2019/06/24 职场文书
如何使用pdb进行Python调试
2021/06/30 Python