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面向对象的作用域链(转载)的更多相关文章

  1. javascript(面向对象,作用域,闭包,设计模式等)

    javascript(面向对象,作用域,闭包,设计模式等) 1. 常用js类定义的方法有哪些? 参考答案:主要有构造函数原型和对象创建两种方法.原型法是通用老方法,对象创建是ES5推荐使用的方法.目前 ...

  2. javascript的关键所在---作用域链

    javascript的关键所在---作用域链 javascript里的作用域是理解javascript语言的关键所在,正确使用作用域原理才能写出高效的javascript代码,很多javascript ...

  3. 认识javascript范围和作用域链

    范围 作用域就是变量和函数的可訪问范围.控制着变量和函数的可见性与生命周期,在JavaScript中变量的作用域有全局作用域和局部作用域. 全局和局部作用域以下用一张图来解释: 单纯的JavaScri ...

  4. javascript闭包和作用域链

    最近在学习前端知识,看到javascript闭包这里总是云里雾里.于是翻阅了好多资料记录下来本人对闭包的理解. 首先,什么是闭包?看了各位大牛的定义和描述各式各样,我个人认为最容易一种说法: 外部函数 ...

  5. javascript笔记:javascript的关键所在---作用域链

    javascript里的作用域是理解javascript语言的关键所在,正确使用作用域原理才能写出高效的javascript代码,很多javascript技巧也是围绕作用域进行的,今天我要总结一下关于 ...

  6. Javascript——闭包、作用域链

    1.闭包:是指有权访问另一个函数作用域中的变量的函数.创建闭包的常见方式:在一个函数内部创建另一个函数. function f(name){ return function(object){ var ...

  7. [译]JavaScript:函数的作用域链

    原文:http://blogs.msdn.com/b/jscript/archive/2007/07/26/scope-chain-of-jscript-functions.aspx 在JavaScr ...

  8. JavaScript中的作用域链原理

    执行环境 作用域链的形成与执行环境(Execution Environment)相关,在JavaScript当中,产生执行环境有如下3中情形: 1 进入全局环境 2 调用eval函数 3 调用func ...

  9. javascript 关于 this 作用域链

    使用 function f() {}  或者 var f = function() {}  来定义的函数,this 是指向 全局对象   var  a = {    b: 1,    c: funct ...

随机推荐

  1. Unity 游戏框架搭建 2019 (二十六) 第一轮整理完结

    昨天呢我们把第八个示例整理完了.整理之后学习了类的第一作用:方法的集合,还有 Obselete 这个 API.并且在进行整理的时候贯彻了我们新的约定和规则:先确保功能有效,再去做变更和删除. 今天我们 ...

  2. Linux基础:Day03

    Linux的网络 以太网的发明--PC之间文件共享情况出现 网卡硬件设备 -- MAC地址  一层:物理层 HUB -- 集线器 总线型结构 泛洪  广播域/冲突域  二层: 在早期的网络中,PC互通 ...

  3. 从零搭建一个SpringCloud项目之Zuul(四)

    整合Zuul 为什么要使用Zuul? 易于监控 易于认证 减少客户端与各个微服务之间的交互次数 引入依赖 <dependency> <groupId>org.springfra ...

  4. mpvue小程序开发

    查阅资料,看官方文档,知道mpvue是一个使用 Vue.js 开发小程序的前端框架(美团的开源项目).框架基于 Vue.js 核心,mpvue 修改了 Vue.js 的 runtime 和 compi ...

  5. Js异步机制的实现

    Js异步机制 JavaScript是一门单线程语言,所谓单线程,就是指一次只能完成一件任务,如果有多个任务,就必须排队,前面一个任务完成,再执行后面一个任务,以此类推.这种模式的好处是实现起来比较简单 ...

  6. "图片组件"组件:<pic> —— 快应用组件库H-UI

     <import name="pic" src="../Common/ui/h-ui/media/c_pic"></import> & ...

  7. SpringBoot 2.x 开发案例之前后端分离鉴权

    前言 阅读本文需要一定的前后端开发基础,前后端分离已成为互联网项目开发的业界标准使用方式,通过Nginx代理+Tomcat的方式有效的进行解耦,并且前后端分离会为以后的大型分布式架构.弹性计算架构.微 ...

  8. Docker命名空间

    命名空间 命名空间( namespace )是 Linux 内核的一个强大特性,为容器虚拟化的实现带来极大便利,利用这 特性,每个容器都可以拥有自己单独的命名空间,运行在其中的应用都像是在独立的操作系 ...

  9. shell命令-while语句

    loop=1 while [ "$loop" -le 10 ] do echo "loop:$loop" loop=$(($loop+2)) done

  10. hexo部署在码云中 无样式问题

    在本地localhost:4000 运行如下 上传码云之后打开Gitee Pages服务 如下 同时控制台打印 解决方法 找到根目录下的_config.yml中的url 和 root # url: h ...