轻松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 相关文章推荐
JavaScript For Beginners(转载)
Jan 05 Javascript
passwordStrength 基于jquery的密码强度检测代码使用介绍
Oct 08 Javascript
js输入框邮箱自动提示功能代码实现
Dec 10 Javascript
extjs 分页使用jsp传递数据示例
Jul 29 Javascript
JS实现在网页中弹出一个输入框的方法
Mar 03 Javascript
基于jQuery+Cookie实现的防止刷新的在线考试倒计时
Jun 19 Javascript
简易的JS计算器实现代码
Oct 18 Javascript
vue + socket.io实现一个简易聊天室示例代码
Mar 06 Javascript
js编写简单的计时器功能
Jul 15 Javascript
小程序实现多列选择器
Feb 15 Javascript
详解如何提升JSON.stringify()的性能
Jun 12 Javascript
在vue中根据光标的显示与消失实现下拉列表
Sep 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
DC漫画《蝙蝠侠和猫女》图透 猫女怀孕老爷当爹
2020/04/09 欧美动漫
JAVA/JSP学习系列之二
2006/10/09 PHP
phpMyAdmin 链接表的附加功能尚未激活的问题
2010/08/01 PHP
php重定向的三种方法分享
2012/02/22 PHP
通过修改Laravel Auth使用salt和password进行认证用户详解
2017/08/17 PHP
PHP依赖注入原理与用法分析
2018/08/21 PHP
双击滚屏-常用推荐
2006/11/29 Javascript
javascript 表单的友好用户体现
2009/01/07 Javascript
JavaScript onkeydown事件入门实例(键盘某个按键被按下)
2014/10/17 Javascript
BOOTSTRAP时间控件显示在模态框下面的bug修复
2015/02/05 Javascript
ECMAScript6函数默认参数
2015/06/12 Javascript
JS+Canvas 实现下雨下雪效果
2016/05/18 Javascript
深入理解js中this的用法
2016/05/28 Javascript
jQuery实现基本动画效果的方法详解
2018/09/06 jQuery
Vue实现兄弟组件间的联动效果
2020/01/21 Javascript
vue使用transition组件动画效果的实例代码
2021/01/28 Vue.js
Python模块搜索路径代码详解
2018/01/29 Python
用Python实现大文本文件切割的方法
2019/01/12 Python
Python中psutil的介绍与用法
2019/05/02 Python
通过python实现随机交换礼物程序详解
2019/07/10 Python
numpy.linalg.eig() 计算矩阵特征向量方式
2019/11/29 Python
Python进行统计建模
2020/08/10 Python
Python3实现英文字母转换哥特式字体实例代码
2020/09/01 Python
css3 flex布局 justify-content:space-between 最后一行左对齐
2020/01/02 HTML / CSS
Fairyseason:为个人和批发商提供女装和配件
2017/03/01 全球购物
MAC Cosmetics巴西官方网站:M·A·C彩妆
2019/04/18 全球购物
毕业生文员求职信
2013/11/03 职场文书
军训自我鉴定200字
2014/02/13 职场文书
财务科科长岗位职责
2014/03/10 职场文书
销售经理竞聘书
2014/03/31 职场文书
班组建设经验交流材料
2014/05/12 职场文书
2014年学生会生活部工作总结
2014/11/07 职场文书
解除租房协议书
2014/12/03 职场文书
2014年城管个人工作总结
2014/12/08 职场文书
食品药品安全责任书
2015/05/11 职场文书
指导教师推荐意见
2015/06/05 职场文书