前言

  通过本文,你大概明白作用域,作用域链是什么,毕竟这也算JS中的基本概念。

一.作用域(scope)

什么是作用域,你可以理解为你所声明变量的可用范围,我在某个范围内申明了一个变量,且这个变量能在这个范围内可用, 那么我可以说此范围就是该变量的作用域。

作用域一般分为局部作用域全局作用域。

怎么理解呢,先说局部作用域。假设我在A范围内用var申明了一个变量a,变量a只能在范围A内使用,超出A范围就调用不到,那么这样的变量a就是局部变量,范围A就是所说的局部作用域。

 function A(){
var a = ;
console.log(a);
}
A();//
console.log(a);//报错,A未定义

假设我们在全局范围(没在任何函数体内)申明了变量b,你可以在任何局部作用域内去使用它,那么我们一般称b为全局变量,包含b的范围就是全局作用域,b随处可用,没任何限制。

 var b = ;
function B(){
console.log(b);
}
B();//
console.log(b);//

我们在上面说,在A范围内用var申明变量a,a为局部变量,当我们不用var申明时,即使在一个局部作用域内,它依旧属于全局变量。

 function A(){
a = ;
console.log(a);
}
A();//
console.log(a);//

只要一个变量申明前面未加任何申明符,那此变量就是全局变量,我们很少这样去做,因为很难保证后期维护不会导致变量申明重名,这样的做法容易造成全局污染。

顺带一提,在函数体内,局部变量的优先级高于同名的全局变量(函数形参也是局部变量),如下:

 var a = ;
function A(a){
console.log(a);
}
A();//

当然,函数的局部变量会被已存在的局部变量所覆盖:

 function A(a){
var a = ;
console.log(a);
}
A();//

有一点需要注意的是,我们在实际开发中往往会遇到作用域嵌套,其实只要清楚作用域间变量是否能使用,是否会被覆盖的关系,就会很清晰了。

 var a = ;
function A(){
var a = ;
function B(){
var a = ;
console.log(a);
}
return B();
}
A();//

二.变量提升

准确来说,在ES6中新增的申明符let已经解决了变量提升这种不严谨的问题,我在这里简单提提,之前也有一篇博文是专门介绍变量提升的。

什么是变量提升呢,就是说,一个变量在对应的作用域内是随处可见的,意思是,就算使用在前,申明在后,它依旧能够使用,不会报错。

具体想了解看这篇文章吧--申明提前,变量申明提前,函数申明提前,申明提前的先后顺序

三.作用域链

我们在上面说,作用域也存在嵌套的问题,那么我们可以这样去理解作用域链,当我们需要某个变量的值时,我们先去理它最近的作用域去找,如果找不套,就找它的上级作用域,依次类推,直到找到全局,如果全都未定义,那就抛出一个错误,如下。

 var a =
function A(){
function B(){
console.log(a);
}
return B();
}
A();//1

可以说,作用链的寻找过程是从内向外的过程,而不是从外到内,可以站在局部作用域去调用全局作用域的属性,反过来是不允许的。

OK,概念大概说到这里吧,嗯,还是来几道题目巩固下。

题目一

 var a=;
function A(){
alert(a);
};
function B(){
var a=;
A();
}
B();//

为什么输出10,而不是20?js中变量的作用域链与定义时的环境有关,与执行时无关。

我们调用函数B后,函数B又调用了函数A,函数A里面没定义变量a但是要用a,函数A只是被B调用且不传参,因此函数A无权使用函数B的局部变量a,而我们在上方还有一个全局变量a,因此这里输出10.

 var a=;
function A(a){
alert(a);
};
function B(){
var a=;
A(a);
}
B();//

这样就可以输出20了,函数B调用函数A的同时传入参数a,函数B提供了变量a,那就输出20了。

题目二

 function aaa(){
a=;
}
alert(a);//报错

想到了一个问题,这里就将题目稍作修改了。我们在前面说,在局部作用域内,不用var 申明一个变量,它也是全局变量,随处可见,那为何在外输出它会报错呢?

函数是个很奇怪的东西,可以这样理解,一个函数当没被调用,它其实是不可见的,它里面的所有变量也不可见,即使a确实是全局变量没错,它还是在是否可见上受到了函数的限制,调用后就可见了。

 function A(){
a=;
}
A()
alert(a);//

那我们改成这样呢?

 alert(a);//报错
function A(){
a=;
}
A();
alert(a)

不是说函数调用后里面的变量a就随便用了吗,怎么上面的又报错了?因为代码都有自己的执行顺序,要知道第一次alert a,此时函数还未被调用,所以就报错了,有点绕,试着理解。

就整理这么多吧,希望有所帮助。

本文思路参考了 博文

JS作用域面试题总结

js作用域与原型的笔试题

JS作用域,作用域,作用链详解的更多相关文章

  1. 你不知道的JavaScript--Item15 prototype原型和原型链详解

    用过JavaScript的同学们肯定都对prototype如雷贯耳,但是这究竟是个什么东西却让初学者莫衷一是,只知道函数都会有一个prototype属性,可以为其添加函数供实例访问,其它的就不清楚了, ...

  2. ext.js的mvc开发模式详解

    ext.js的mvc开发模式详解和环境配置 在JS的开发过程中,大规模的JS脚本难以组织和维护,这一直是困扰前端开发人员的头等问题.Extjs为了解决这种问题,在Extjs 4.x版本中引入了MVC开 ...

  3. JS中的event 对象详解

    JS中的event 对象详解   JS的event对象 Event属性和方法:1. type:事件的类型,如onlick中的click:2. srcElement/target:事件源,就是发生事件的 ...

  4. js中鼠标滚轮事件详解

    js中鼠标滚轮事件详解   (以下内容部分内容参考了http://adomas.org/javascript-mouse-wheel/ ) 之前js 仿Photoshop鼠标滚轮控制输入框取值中已使用 ...

  5. Android JNI作用及其详解

    Android JNI作用及其详解 Java Native Interface (JNI)标准是Java平台的一部分,它允许Java代码和其他语言写的代码进行交互.JNI 是本地编程接口,它使得在 J ...

  6. 微信JS接口汇总及使用详解

    这篇文章主要介绍了微信JS接口汇总及使用详解,十分的全面.详尽,包含分享到朋友圈,分享给朋友,分享到QQ,拍照或从手机相册中选图,识别音频并返回识别结果,使用微信内置地图查看位置等接口,有需要的小伙伴 ...

  7. “全栈2019”Java异常第十五章:异常链详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java异 ...

  8. js中中括号,大括号使用详解

    js中中括号,大括号使用详解 一.总结 一句话总结:{ } 是一个对象,[ ] 是一个数组 1.js大括号{}表示什么意思? 对象 { } 大括号,表示定义一个对象,大部分情况下要有成对的属性和值,或 ...

  9. js对象浅拷贝和深拷贝详解

    js对象浅拷贝和深拷贝详解 作者:i10630226 字体:[增加 减小] 类型:转载 时间:2016-09-05我要评论 这篇文章主要为大家详细介绍了JavaScript对象的浅拷贝和深拷贝代码,具 ...

随机推荐

  1. 团队项目第6周 - Alpha阶段项目复审 - 天冷记得穿秋裤队

    团队项目第六周 - Alpha阶段项目复审 - 天冷记得穿秋裤队 经小组讨论得出以下排名 小组 优点 缺点,bug报告 最终名次 冲鸭队 一款融合了2048和俄罗斯方块的小游戏,题材十分新颖,游戏充满 ...

  2. EBS 取消“是否提交另一项请求”提示

    在使用EBS提交请求后,总要弹出“是否提交另一项请求”的提示,而我们往往选择“否”,这个提示就显得多余. 为了减轻这“多一步”的负担,取消“是否提交另一项请求”的提示,设置方法如下: 以下profil ...

  3. 二、基于kubernetes构建Docker集群环境实战

    kubernetes是google公司基于docker所做的一个分布式集群,有以下主件组成 etcd: 高可用存储共享配置和服务发现,作为与minion机器上的flannel配套使用,作用是使每台 m ...

  4. 实验8 LCD8*8点阵

    1.控制点阵红绿交替显示,分别从上到下,从左到右循环闪烁三次 接线: P0接J12.P1接J20.P2接J19 /** 1.控制点阵红绿交替显示,分别从上到下,从左到右循环闪烁三次 **/ #incl ...

  5. 通过键盘控制改变物体transform值

    通过键盘控制改变物体transform值 private Vector3 trans; //使用Rotate绕y 轴旋转 transform.Rotate(new Vector3(0,Input.Ge ...

  6. bootstrap基础学习小记(一)简介模板、全局样式

    2011年,twitter的“一小撮”工程师为了提高他们内部的分析和管理能力,用业余时间为他们的产品构建了一套易用.优雅.灵活.可扩展的前端工具集--BootStrap.Bootstrap由MARK ...

  7. CODE FIRST之空数据模型

    1.首先添加空Code Firtst模型 2.新建两个实体类,关系一对多 public class UserInfo { public UserInfo() { OrderInfo = new Has ...

  8. Entity Framework 6 多对多增改操作指南

    问题描述 在很多系统中,存在多对多关系的维护.如下图: 这种多对多结构在数据库中大部分有三个数据表,其中两个主表,还有一个关联表,关联表至少两个字段,即左表主键.右表主键. 如上图,其中的Suppli ...

  9. C语言Socket-模拟远程CMD(客户端向服务器发送命令,服务器执行该命令)

    服务端(server) #include <stdio.h> #include <winsock2.h> #pragma comment(lib,"ws2_32.li ...

  10. Maximum repetition substring(POJ - 3693)(sa(后缀数组)+st表)

    The repetition number of a string is defined as the maximum number \(R\) such that the string can be ...