JavaScript 词法、静态、动态作用域初级理解

开始之前

  由于本人也是JavaScript初学者,记录学习经过,怕以后会忘记。

  对于JavaScript 初学者来说,最难的不是代码部分,而是对很多书籍中的术语的理解,大多时候想要理解一段JavaScript书籍中的解释内容,就会涉及很多术语,在术语不通的情况下都会对内容理解偏差(导致很难记住所学内容),由于本人在阅读书籍时经常会遇到这一问题,所以今天将记下这一基础内容。

一、需要关注点

  1)执行环境(作用域)函数执行环境 变量作用域

  2)函数作用域和声明提前

  3)自由变量

  4)词法作用域和静态作用域

  5)动态作用域

二、解释

  1)执行环境(作用域)变量作用域

    说到执行环境这个词,对于看过JavaScript高级程序设计的同学并不陌生,那么我们就先来看看什么是执行环境:

    1.执行环境:简称:“环境”,是JavaScript中最重要的一个概念。执行环境定义了变量或函数有权访问的其他数据,决定了它们各自的行为,每个执行环境都有一个与之关联的“变量对象(variable object)”,环境中定义的所有变量和函数都保存在这个对象中。我们编写的代码是无法访问这个对象的,但解析器在处理数据时会在后台使用它。

    2.全局执行环境是最外围的一个执行环境,在Web浏览器中,全局执行环境被认为是window对象,因此所有全局变量和函数都是作为window对象的属性和方法来创建的。某个执行环境中的所有代码执行完毕后,该环境就会被销毁,保存在其中的所有变量和函数定义也随之销毁。

    3.函数执行环境:每个函数都有自己的执行环境,当执行流进入一个函数时,函数的环境就会被推入一个环境栈中。而在函数执行之后,栈将其环境弹出,把控制权返回给之前的执行环境。 

    4.作用域链:它的用途是保证对执行环境有权访问的所有变量和函数的有序访问,作用域链的前端,始终都是当前执行的代码所在的环境的变量对象。当代码在一个执行环境中执行时,会创建变量对象的一个作用域链(scope chain)。

  2)声明提前

    1.声明提前:javascript的函数作用域是指在函数内声明的所有变量在函数体内始终是可见的,这意味着变量在声明之前是可用的,这也是原因。这步操作是在javascript "预编译"时进行的,是在代码运行之前。

// 局部变量优先于全局变量
// 函数嵌套的情况下,最内层函数变量优先于在它之上的函数变量
var scope = ‘global scope‘;

function checkScope() {
    // body...
    var scope = ‘local scope‘;

    function nested() {
        var scope = ‘nested scope‘;
        return scope;
    }
    return nested();
}

var scope = checkScope();
console.log(‘varable scope :‘, scope) // ‘nested scope‘

  3)自由变量:在A作用域中使用的变量x,却没有在A作用域中声明(即在其他作用域中声明的),对于A作用域来说,x就是一个自由变量。

ar x = 10;
function fn(){
	var b = 20;
	console.log(x + b); // x 就是一个自由变量。
}

  4)词法作用域和静态作用域:词法作用域等同于静态作用域,静态作用域规则查找一个变量声明时依赖的是源程序中块之间的静态关系;

  5)动态作用域规则依赖的是程序执行时的函数调用顺序。

    静态作用域和动态作用域的一个重要区别在于:
    静态作用域规则查找一个变量声明时依赖的是源程序中块之间的静态关系;
    而动态作用域规则依赖的是程序执行时的函数调用顺序。
    说的具体点,就是静态作用域查找的是距离当前作用域最近的外层作用域中同名标识符的声明,
    而动态作用域则是查找最近的活动记录

关于作用域几篇比叫好的文章:

http://www.cnblogs.com/zxj159/archive/2013/05/17/3084598.html

http://www.cnblogs.com/wangfupeng1988/p/3992795.html

时间: 2024-08-05 03:19:12

JavaScript 词法、静态、动态作用域初级理解的相关文章

深入理解javascript作用域系列第二篇——词法作用域和动态作用域

× 目录 [1]词法 [2]动态 前面的话 大多数时候,我们对作用域产生混乱的主要原因是分不清楚应该按照函数位置的嵌套顺序,还是按照函数的调用顺序进行变量查找.再加上this机制的干扰,使得变量查找极易出错.这实际上是由两种作用域工作模型导致的,作用域分为词法作用域和动态作用域,分清这两种作用域模型就能够对变量查找过程有清晰的认识.本文是深入理解javascript作用域系列第二篇——词法作用域和动态作用域 词法作用域 第一篇介绍过,编译器的第一个工作阶段叫作分词,就是把由字符组成的字符串分解成

JavaScript词法作用域与调用对象

关于 Javascript 的函数作用域.调用对象和闭包之间的关系很微妙,关于它们的文章已经有很多,但不知道为什么很多新手都难以理解.我就尝试用比较通俗的语言来表达我自己的理解吧. 作用域 Scope Javascript 中的函数属于词法作用域,也就是说函数在它被定义时的作用域中运行而不是在被执行时的作用域内运行.这是犀牛书上的说法.但"定义时"和"执行(被调用)时"这两个东西有些人搞不清楚.简单来说,一个函数A在"定义时"就是 functio

静态作用域和动态作用域

静态作用域指的是一段代码,在它执行之前就已经确定了它的作用域,简单来说就是在执行之前就确定了它可以应用哪些地方的作用域(变量). 动态作用域–函数的作用域是在函数调用的时候才决定的 JavaScript采用的是词法作用域即静态作用域: // 静态作用域: var a = 10; function fn() { var b = 1; console.log(a + b); } fn(); // 11 在创建fn函数时的时候就已经确定了它可以作用哪些变量,如果函数fn里面有变量a就直接操作变量a,

深入理解javascript中的动态集合——NodeList、HTMLCollection和NamedNodeMap

× 目录 [1]NodeList [2]HTMLCollection [3]NamedNodeMap[4]注意事项 前面的话 一说起动态集合,多数人可能都有所了解.但是,如果再深入些,有哪些动态集合,以及这些动态集合有什么表现.区别和联系?可能好多人就要摇头了.本文就javascript中的动态集合做详细介绍 NodeList NodeList实例对象是一个类数组对象,它的成员是节点对象,包括childNodes和querySelectorAll()方法返回值 <div id="test&

关于静态库和动态库的理解(C++)

库的存在,是软件模块化的基础. 库存在的意义: } 库是别人写好的现有的,成熟的,可以复用的代码,你可以使用但要记得遵守许可协议.      } 现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常.      } 共享库的好处是,不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例.带来好处的同时,也会有问题!如经典的DLL Hell问题,这就要求在设计DLL时候应该向下兼容,然而要保证DLL完全向下兼容却是几乎不能的. 库有两种:静

深入作用域之静态作用域与动态作用域

概念: 静态作用域指的是一段代码,在它执行之前就已经确定了它的作用域,简单来说就是在执行之前就确定了它可以应用哪些地方的作用域(变量). 动态作用域在代码执行的时候才确定它的作用域的,以及作用域链. 静态作用域: var a = 10; function fn(){ var b = 1; console.log(a+b); } fn(); //11 在创建函数fn的时候就已经确定了它可以作用那些变量,如果函数fn里面有变量a就直接作用函数fn里面的变量a,如果没有就往上一级找,这就是静态作用域.

区分词法作用域(js)与动态作用域(精!)

在js学习中,词法作用域是必须要掌握的! 在这里,我将总结一下<你不知道的JS>一书中词法作用域的重点并分享给大家! 首先带来一段代码示例: function foo(){ console.log(a);//2 } function bar(){ var a = 3; foo(); } var a = 2; bar(); js词法作用域输出结果:"2"; 动态作用域输出结果:"3" 下面我将对两种作用域的输出结果进行分析: #在对结果分析之前首先我们要了

词法作用域 vs 动态作用域

词法作用域 vs 动态作用域 链接:https://www.jianshu.com/p/cdebb5965000 scheme是一门采用词法作用域(lexical scoping)的lisp方言,这个设计是从alogol语言里借鉴过来的.现在,词法作用域已经被许多lisp方言所吸收,实践表明,这的确是一项正确的设计,避免了很多奇怪的错误,比较符合人类的思维习惯. 但是,在某些场合下,动态作用域又是很有用的特性,比如emacs lisp里面就默认采用动态作用域. 下面的程序演示了词法作用域与动态作

关于JavaScript中没有块级作用域的理解

引用<JavaScript权威指南>(第六版)中的举例 代码段1: var scope="global"; function f(){ console.log(scope); scope="local" console.log(scope); } f(); 会输出什么? 答案:undefined  global 代码段2: var scope="global"; function f(){ var scope; console.log