JavaScript作用域原理(一)——作用域链

简介:

一、作用域的描述

JavaScript权威指南中对作用域有一句很精辟的描述:“JavaScript中的函数运行在它们被定义的作用域里,而不是它们被执行的作用域里。”

在JavaScript中,作用域的概念和其他语言差不多,在每次调用一个函数的时候,就会进入一个函数内的作用域,当从函数返回以后,就返回调用前的作用域。

 

验证下刚那句权威指南中的话:

<p id="scope1" style="color:red"></p>
     function echo(p, html) {
            p.innerHTML += html + '<br/>';
        }
        //1、
        var position = 'out';
        var pscope1 = document.getElementById('scope1');
        function scope1() {
            echo(pscope1, position);
        }
        function set1() {
            var position = 'in';
            scope1();
        }
        set1();

1、变量scope1定位到一个p标签,用于打印信息的显示

2、echo是一个自定义的函数,用于打印信息,形参一个是p标签,一个是需要打印的信息内容

3、最后打印出的是“out”,由于打印操作在scope1函数中,scope1中没有变量position,只能往外一层的作用域中查找,作用域关系如下图所示:

4、调用set1的作用域链大致样子如下:

 

二、作用域的实现

作用域的实现,并非用“堆栈”方式,而是使用列表,ECMA262中所述如下:

  1. 任何执行上下文时刻的作用域, 都是由作用域链(scope chain)来实现

  2. 在一个函数被定义的时候, 会将它定义时刻的scope chain链接到这个函数对象的[[scope]]属性

  3. 在一个函数对象被调用的时候,会创建一个活动对象(也就是一个对象), 然后对于每一个函数的形参,都命名为该活动对象的命名属性, 然后将这个活动对象做为此时的作用域链(scope chain)最前端, 并将这个函数对象的[[scope]]加入到scope chain中

 

再来看下两个实例,练练手:

     function function1() {
            var x = 'in function1';
            function inner1() {
                x = 'in inner1'; //没有加var,等同于在外面这个函数中做声明
            }
            inner1();
            echo(pscope1, x);
        }
        function1();

最终打印出来的结果是“in inner1”

 

     function function2() {
            var x = 'in function2';
            function inner2() {
                echo(pscope1, x); 
                var x = 'in inner2'; //加var
                echo(pscope1, x); 
            }
            inner2();
        echo(pscope1, x);
        }
        function2();

第一个echo将打印出“undefined”,第二个echo打印出“in inner2”,第三个echo打印出“in function2”。

上面的inner2等同于下面的代码:

        function inner2() {
                var x
                echo(pscope1, x); //这个时候x还未定义
                x = 'in inner2'; 
                echo(pscope1, x); 
            }

 

 

对作用域链的理解上可能还有些问题,欢迎大家来指正。

 

demo下载:

http://download.csdn.net/detail/loneleaf1/7983577

 

参考资料:

http://www.laruence.com/2009/05/28/863.html Javascript作用域原理

http://www.cnblogs.com/lhb25/archive/2011/09/06/javascript-scope-chain.html JavaScript 开发进阶:理解 JavaScript 作用域和作用域链

http://www.cnblogs.com/zxj159/archive/2013/05/30/3107923.html Javascript之匿名函数(模仿块级作用域)

http://www.web-tinker.com/article/20331.html try-catch语句的“伪块作用域”

http://msdn.microsoft.com/zh-cn/library/bzt2dkta%28v=vs.94%29.aspx 变量作用域 (JavaScript)

http://www.cnblogs.com/rubylouvre/archive/2009/08/21/1551270.html javascript变量的作用域

http://www.nowamagic.net/librarys/veda/detail/896 深入浅出JavaScript变量作用域





    本文转自 咖啡机(K.F.J)   博客园博客,原文链接:http://www.cnblogs.com/strick/p/3992745.html,如需转载请自行联系原作者


相关文章
|
14天前
|
JavaScript 前端开发
js变量的作用域、作用域链、数据类型和转换应用案例
【4月更文挑战第27天】JavaScript 中变量有全局和局部作用域,全局变量在所有地方可访问,局部变量只限其定义的代码块。作用域链允许变量在当前块未定义时向上搜索父级作用域。语言支持多种数据类型,如字符串、数字、布尔值,可通过 `typeof` 检查类型。转换数据类型用 `parseInt` 或 `parseFloat`,将字符串转为数值。
18 1
|
1月前
|
JavaScript 算法 前端开发
JS垃圾回收机制的原理
JS垃圾回收机制的原理
|
1月前
|
存储 JavaScript 前端开发
解释 JavaScript 中的作用域和作用域链的概念。
【4月更文挑战第4天】JavaScript作用域定义了变量和函数的可见范围,静态决定于编码时。每个函数作为对象拥有`scope`属性,关联运行期上下文集合。执行上下文在函数执行时创建,定义执行环境,每次调用函数都会生成独特上下文。作用域链是按层级组织的作用域集合,自内向外查找变量。变量查找遵循从当前执行上下文到全局上下文的顺序,若找不到则抛出异常。
21 6
|
1月前
|
JavaScript
作用域和作用域链(js的问题)
作用域和作用域链(js的问题)
|
1天前
|
JavaScript 前端开发
深入了解前端框架Vue.js的响应式原理
本文将深入探讨Vue.js前端框架的核心特性之一——响应式原理。通过分析Vue.js中的数据绑定、依赖追踪和虚拟DOM等机制,读者将对Vue.js的响应式系统有更深入的理解,从而能够更好地利用Vue.js构建灵活、高效的前端应用。
|
12天前
|
编解码 JavaScript 前端开发
【专栏】介绍了字符串Base64编解码的基本原理和在Java、Python、C++、JavaScript及Go等编程语言中的实现示例
【4月更文挑战第29天】本文介绍了字符串Base64编解码的基本原理和在Java、Python、C++、JavaScript及Go等编程语言中的实现示例。Base64编码将24位二进制数据转换为32位可打印字符,用“=”作填充。文中展示了各语言的编码解码代码,帮助开发者理解并应用于实际项目。
|
15天前
|
JavaScript 前端开发
js原生自调用函数原理
JavaScript中的IIFE(Immediately Invoked Function Expression)是定义后立即执行的函数表达式。它有两种实现方式:匿名函数表达式 `(function() { /* 函数体 */ })()` 和命名函数声明 `(function myFunction() { /* 函数体 */ })()`。IIFE提供封闭作用域,防止变量冲突,常用于创建私有作用域、封装代码和避免变量提升问题。执行后,IIFE内部的变量和函数会被销毁,除非被特意暴露。
|
16天前
|
前端开发 JavaScript
前端 富文本编辑器原理——从javascript、html、css开始入门(二)
前端 富文本编辑器原理——从javascript、html、css开始入门
26 0
前端 富文本编辑器原理——从javascript、html、css开始入门(二)
|
16天前
|
前端开发 JavaScript 索引
前端 富文本编辑器原理——从javascript、html、css开始入门(一)
前端 富文本编辑器原理——从javascript、html、css开始入门
36 0
|
19天前
|
前端开发 JavaScript 编译器
深入解析JavaScript中的异步编程:Promises与async/await的使用与原理
【4月更文挑战第22天】本文深入解析JavaScript异步编程,重点讨论Promises和async/await。Promises用于管理异步操作,有pending、fulfilled和rejected三种状态。通过.then()和.catch()处理结果,但可能导致回调地狱。async/await是ES2017的语法糖,使异步编程更直观,类似同步代码,通过事件循环和微任务队列实现。两者各有优势,适用于不同场景,能有效提升代码可读性和维护性。