轻松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 相关文章推荐
JsEasy简介 JsEasy是什么?与下载
Mar 07 Javascript
JavaScript 字符串乘法
Aug 20 Javascript
JS date对象的减法处理实现代码
Dec 28 Javascript
Kibo 用于处理键盘事件的Javascript工具库
Oct 28 Javascript
使用node.js 获取客户端信息代码分享
Nov 26 Javascript
JS+CSS实现的拖动分页效果实例
May 11 Javascript
js不间断滚动的简单实现
Jun 03 Javascript
jQuery:unbind方法的使用详解
Aug 14 jQuery
vuex与组件联合使用的方法
May 10 Javascript
JS逻辑运算符短路操作实例分析
Jul 09 Javascript
JS实现贪吃蛇游戏
Nov 15 Javascript
在Vue中使用antv的示例代码
Jun 29 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
全国FM电台频率大全 - 31 新疆维吾尔族自治区
2020/03/11 无线电
PHP网页游戏学习之Xnova(ogame)源码解读(一)
2014/06/23 PHP
php购物车实现方法
2015/01/03 PHP
WordPress中调试缩略图的相关PHP函数使用解析
2016/01/07 PHP
Laravel 在views中加载公共页面的实现代码
2019/10/22 PHP
带左右箭头图片轮播的JS代码
2013/12/18 Javascript
javascript浏览器窗口之间传递数据的方法
2015/01/20 Javascript
用JavaScript实现对话框的教程
2015/06/04 Javascript
jquery实现简单手风琴菜单效果实例
2015/06/13 Javascript
javascript实现方法调用与方法触发小结
2016/03/26 Javascript
使用jquery提交form表单并自定义action的实现代码
2016/05/25 Javascript
zepto与jquery的区别及zepto的不同使用8条小结
2016/07/28 Javascript
微信小程序 教程之模块化
2016/10/17 Javascript
vue父子组件的数据传递示例
2017/03/07 Javascript
微信小程序新增的拖动组件movable-view使用教程
2017/05/20 Javascript
微信小程序基于slider组件动态修改标签透明度的方法示例
2017/12/04 Javascript
js构造函数创建对象是否加new问题
2018/01/22 Javascript
原生JS封装_new函数实现new关键字的功能
2018/08/12 Javascript
VUE脚手架的下载和配置步骤详解
2019/04/01 Javascript
2019年度web前端面试题总结(主要为Vue面试题)
2020/01/12 Javascript
python实现验证码识别功能
2018/06/07 Python
Python动态生成多维数组的方法示例
2018/08/09 Python
PyQt5实现简易计算器
2020/05/30 Python
windows中安装Python3.8.0的实现方法
2019/11/19 Python
python递归调用中的坑:打印有值, 返回却None
2020/03/16 Python
Python 通过爬虫实现GitHub网页的模拟登录的示例代码
2020/08/17 Python
css3实现书本翻页效果的示例代码
2021/03/08 HTML / CSS
印度最大的旅游网站:MakeMyTrip
2016/10/05 全球购物
英国首屈一指的票务公司:See Tickets
2019/05/11 全球购物
荷兰在线啤酒店:Beerwulf
2019/08/26 全球购物
2014年幼儿园植树节活动方案
2014/03/02 职场文书
十佳护士先进事迹
2014/05/08 职场文书
四风批评与自我批评发言稿
2014/10/14 职场文书
党员组织生活会发言材料
2014/10/17 职场文书
毕业生自我鉴定范文
2019/05/13 职场文书
Python Matplotlib库实现画局部图
2021/11/17 Python