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语言中无块级作用域
|
1
2
3
4
5
6
7
|
function Main(){ if(1==1){ var name = 'seven'; } console.log(name);}// 输出: seven |
补充:标题之所以添加双引号是因为JavaScript6中新引入了 let 关键字,用于指定变量属于块级作用域。
二、JavaScript采用函数作用域
在JavaScript中每个函数作为一个作用域,在外部无法访问内部作用域中的变量。
|
1
2
3
4
5
6
7
8
9
|
function Main(){ var innerValue = 'seven';}Main();console.log(innerValue);// 报错:Uncaught ReferenceError: innerValue is not defined |
三、JavaScript的作用域链
由于JavaScript中的每个函数作为一个作用域,如果出现函数嵌套函数,则就会出现作用域链。
|
1
2
3
4
5
6
7
8
9
10
11
|
xo = 'alex'; function Func(){ var xo = "seven"; function inner(){ var xo = 'alvin'; console.log(xo); } inner();}Func(); |
如上述代码则出现三个作用域组成的作用域链,如果出现作用域链后,那么寻找变量时候就会出现顺序,对于上述实例:
当执行console.log(xo)时,其寻找顺序为根据作用域链从内到外的优先级寻找,如果内层没有就逐步向上找,直到没找到抛出异常。

四、JavaScript的作用域链执行前已创建
JavaScript的作用域在被执行之前已经创建,日后再去执行时只需要按照作用域链去寻找即可。
示例一:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
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();】时,会根据已经存在的作用域链去寻找变量。
示例二:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
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”。
示例三:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
xo = 'alex';<br>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中如果不创建变量,直接去使用,则报错:
|
1
2
|
console.log(xxoo);// 报错:Uncaught ReferenceError: xxoo is not defined |
JavaScript中如果创建值而不赋值,则该值为 undefined,如:
|
1
2
3
|
var xxoo;console.log(xxoo);// 输出:undefined |
在函数内如果这么写:
|
1
2
3
4
5
6
7
|
function Foo(){ console.log(xo); var xo = 'seven';}Foo();// 输出:undefined |
上述代码,不报错而是输出 undefined,其原因是:JavaScript的函数在被执行之前,会将其中的变量全部声明,而不赋值。所以,相当于上述实例中,函数在“预编译”时,已经执行了var xo;所以上述代码中输出的是undefined。
JavaScript面向对象的作用域链(转载)的更多相关文章
- javascript(面向对象,作用域,闭包,设计模式等)
javascript(面向对象,作用域,闭包,设计模式等) 1. 常用js类定义的方法有哪些? 参考答案:主要有构造函数原型和对象创建两种方法.原型法是通用老方法,对象创建是ES5推荐使用的方法.目前 ...
- javascript的关键所在---作用域链
javascript的关键所在---作用域链 javascript里的作用域是理解javascript语言的关键所在,正确使用作用域原理才能写出高效的javascript代码,很多javascript ...
- 认识javascript范围和作用域链
范围 作用域就是变量和函数的可訪问范围.控制着变量和函数的可见性与生命周期,在JavaScript中变量的作用域有全局作用域和局部作用域. 全局和局部作用域以下用一张图来解释: 单纯的JavaScri ...
- javascript闭包和作用域链
最近在学习前端知识,看到javascript闭包这里总是云里雾里.于是翻阅了好多资料记录下来本人对闭包的理解. 首先,什么是闭包?看了各位大牛的定义和描述各式各样,我个人认为最容易一种说法: 外部函数 ...
- javascript笔记:javascript的关键所在---作用域链
javascript里的作用域是理解javascript语言的关键所在,正确使用作用域原理才能写出高效的javascript代码,很多javascript技巧也是围绕作用域进行的,今天我要总结一下关于 ...
- Javascript——闭包、作用域链
1.闭包:是指有权访问另一个函数作用域中的变量的函数.创建闭包的常见方式:在一个函数内部创建另一个函数. function f(name){ return function(object){ var ...
- [译]JavaScript:函数的作用域链
原文:http://blogs.msdn.com/b/jscript/archive/2007/07/26/scope-chain-of-jscript-functions.aspx 在JavaScr ...
- JavaScript中的作用域链原理
执行环境 作用域链的形成与执行环境(Execution Environment)相关,在JavaScript当中,产生执行环境有如下3中情形: 1 进入全局环境 2 调用eval函数 3 调用func ...
- javascript 关于 this 作用域链
使用 function f() {} 或者 var f = function() {} 来定义的函数,this 是指向 全局对象 var a = { b: 1, c: funct ...
随机推荐
- python:列表切片知识的总结
列表的切片操作时对其中的单个或者多个索引对应元素的操作,具有如下特点: ①.切片区间是左闭右开区间 ②.切片的下标可以表示负数,-1表示倒数第一个数,-2表示倒数第二个数 ③.默认步长是1,可增加第三 ...
- Linux基础:Day04
进程管理1.操作系统基础 调用:kernel通过给应用程序提供system call方式来提供硬件资源: 注意:这个应用程序也包括库文件: 库文件是运行在ring 0上的一段程序代码,不对客户直接 ...
- pip 安装 request 失败
C:\Program Files\Python35\Scripts>pip install requests Collecting requests Using cached requests- ...
- MyBatis(六):SqlSession执行源码分析
SqlSession执行源码分析 针对以下代码 public class MybatisUtils { private static SqlSessionFactory sqlSessionFacto ...
- android 软件(app)之家庭版记账本首次进行helloword等相关测试
在进行对于app的创建之前是对于android studio的相关安装的环境的配置,完成这些之后自己就写个一个简单的helloword的实例进行了测试.之后通过进一步的向下挖掘,发现当将hellowo ...
- vue-cli3 按需引入 element-ui 报错
报错信息: Cannot find module 'babel-preset-es2015' from .... 解决办法: 安装最新的 Babel 编译插件:@babel/preset-env 修改 ...
- Python线程和协程CPU资源利用率测试
前言介绍 协程 ,又称为微线程,它是实现多任务的另一种方式,只不过是比线程更小的执行单元.因为它自带CPU的上下文,这样只要在合适的时机,我们可以把一个协程切换到另一个协程.通俗的理解: 在一个线程中 ...
- java中JVM虚拟机内存模型详细说明
java中JVM虚拟机内存模型详细说明 2012-12-12 18:36:03| 分类: JAVA | 标签:java jvm 堆内存 虚拟机 |举报|字号 订阅 JVM的内部结构 ...
- AJ学IOS(10)UI之_NSTimer_ios计时器
AJ分享,必须精品 先看效果 代码 #import "NYViewController.h" @interface NYViewController () <UIAlertV ...
- G++编译链接的那些事
语言 CPP 前言 虽然 VSCodeC++ 编辑器非常受大家的欢迎,无论是大佬还是小白都说对其爱不释手... 我...用了一段时间后发现实在是麻烦,配置往往花费我大量时间.可以说真的是吃力不 ...