轻松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加密解密7种方法总结分析
Oct 07 Javascript
jQuery EasyUI API 中文文档 - EasyLoader 加载器
Sep 29 Javascript
很好用的js日历算法详细代码
Mar 07 Javascript
如何在JavaScript中实现私有属性的写类方式(二)
Dec 04 Javascript
从QQ网站中提取的纯JS省市区三级联动菜单
Dec 25 Javascript
JavaScript实现重置表单(reset)的方法
Apr 02 Javascript
jquery+ajax实现直接提交表单实例分析
Jun 17 Javascript
原生JS实现图片轮播与淡入效果的简单实例
Aug 21 Javascript
漂亮实用的页面loading(加载)封装代码
Feb 03 Javascript
node.js到底要不要加分号浅析
Jul 11 Javascript
webpack常用配置总览(小结)
Nov 18 Javascript
Vue路由的模块自动化与统一加载实现
Jun 05 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获取url字符串截取路径的文件名和扩展名的函数
2010/01/22 PHP
关于查看MSSQL 数据库 用户每个表 占用的空间大小
2013/06/21 PHP
php两种无限分类方法实例
2015/04/21 PHP
YII框架页面缓存操作示例
2019/04/29 PHP
判定是否原生方法的JS代码
2013/11/12 Javascript
Node.js中使用计时器定时执行函数详解
2014/08/15 Javascript
js图片模糊切换显示特效的方法
2015/02/17 Javascript
jQuery结合CSS制作动态的下拉菜单
2015/10/27 Javascript
学习javascript面向对象 理解javascript原型和原型链
2016/01/04 Javascript
jQuery解决浏览器兼容性问题案例分析
2016/04/15 Javascript
AngularJs Understanding the Model Component
2016/09/02 Javascript
Bootstrap表单控件使用方法详解
2017/01/11 Javascript
Node.js连接mongodb实例代码
2017/06/06 Javascript
自定义PC微信扫码登录样式写法
2017/12/12 Javascript
微信小程序sessionid不一致问题解决
2019/08/30 Javascript
移动端手指操控左右滑动的菜单
2019/09/08 Javascript
ES6实现图片切换特效代码
2020/01/14 Javascript
vue 实现在同一界面实现组件的动态添加和删除功能
2020/06/16 Javascript
Vue 监听元素前后变化值实例
2020/07/29 Javascript
ReactRouter的实现方法
2021/01/25 Javascript
Python中replace方法实例分析
2014/08/20 Python
Python序列循环移位的3种方法推荐
2018/04/09 Python
python的schedule定时任务模块二次封装方法
2019/02/19 Python
Python爬虫动态ip代理防止被封的方法
2019/07/07 Python
Python学习笔记之错误和异常及访问错误消息详解
2019/08/08 Python
中邮全球便购:中国邮政速递物流
2017/03/04 全球购物
百思买加拿大:Best Buy Canada
2018/03/20 全球购物
创业计划书如何编写
2014/02/06 职场文书
我有一个梦想演讲稿
2014/05/05 职场文书
领导干部廉政自律承诺书
2014/05/26 职场文书
2014年教师节演讲稿
2014/09/03 职场文书
教师思想作风整顿个人剖析材料
2014/10/10 职场文书
开平碉楼导游词
2015/02/06 职场文书
求职意向书范本
2015/05/11 职场文书
党组织结对共建协议书
2016/03/23 职场文书
Python MNIST手写体识别详解与试练
2021/11/07 Python