什么是变量,什么是作用域?

    

     变量:简单来说就是在特定时间内保存特定值的一个名字而已,由于不存在定义某个变量必须要保存某种数据类型值的规则,所以变量的值及其数据类型可以在脚本生命周期内任意改变,变量可能包含两种不同的数据类型得值:基本类型值和引用类型值。基本数据类型包括:Undedind、Null、Boolean、Number、String和Symbol(es6新增),同时Boolean、Number、String和Symbol也叫基本包装类型。引用类型:简单来说,除了所有基本类型剩下的就是引用类型了。可能不严谨,先这样对付看吧。

      作用域:我们已经知道了变量的作用其实就是存储值,那么我们要怎么样才能对值进行访问或者修改?换句话说,这些变量住在哪里呢,更重要的是我们(程序)要如何找到他们?像莎士比亚说得那样:To be, or not to be: that is the question!所以我们需要一套设计良好的规则来存储变量,并且可以方便的找到这些变量,这套规则就叫作用域!

   

  编译原理

    在了解作用于规则前,我们先要知道编译原理,即我们的代码写下之后是怎么工作的。在强类型语言中,程序中要执行一段源代码首先要经过编译,编译过程有三个步骤:

      1、分词/词法分析。这个过程将字符组成的字符串分解成有意义的代码块,这些代码块被称为词法单元,例如 var a = 2;这段代码通常会被分解成为下面这些词法单元:var、a、=、2、;。空格是否被当作词法单元取决于空格对于这门语言是否有意义。

      2、解析/语法分析。这个过程是将词法单元数组转换成一个由元素逐级嵌套所组成的代表程序语法结构的树,叫“抽象语法树”(Abstract Syntax Tree,AST)。简单来说,对于编程语言下的源代码,通过构建语法树的形式将源代码中的代码映射到树中的每一个节点上。

      3、代码生成。将AST(抽象语法树)转换为可执行的代码这一过程叫做代码生成。简单来说就是将 var a  = 2;的AST转化成机器能认识的指令,创建一个变量a,然后他的值2储存在a中。

   

     比起那些编译过程只有三个步骤的编译器,JavaScript引擎要复杂的多,在语法分析和代码生成阶段有特定的步骤来对性能进行优化,包括对冗余元素进行优化等,具体有哪些步骤,我也不知道,因为编译原理这段内容是摘抄《《你不知道的JavaScirpt 上卷》》书中的原话,哈哈哈,是不是很吃精!!!JS的编译大部分发生在代码执行前的,并且编译完成马上执行。

   

  理解作用域

    请看var a = 2;这段代码,正常人会认为这是一句生明,因为语句中没有‘,’或者’。‘等语句分隔符号,但是在JS引擎中认为这里有两个声明:变量生命和赋值生明。首先是词法分析过程,将var a = 2;分解成词法单元,然后语法分析生成抽象语法树,最后执行代码。具体一点说,var a = 2;会分解成var a 和a = 2;当编译器遇到var  a,时,编译器会询问作用域是否已经存在一个该名称的变量存于同一个作用域中,如果是则会忽略该生明(es6中新增的let和const情况有点不太一样),如果没有存在,则在当前作用域中生命一个新的变量,命名为a。接下来编译器会为引擎生成运行时所需要的代码,这段代码来处理a=2这个赋值操作。引擎运行时首先会在当前作用域中查找是否有一个叫做a的变量,如果有就赋值,如果没有就继续向上一级作用域查找,如果实在是找不到,找到了作用域顶层全局作用域也找不到,那么就会抛出一个错误。所以变量赋值操作总会执行两个步骤,如果变量未声明则在当前作用域中生名一个变量(严格模式下如果给未声明的变量赋值会报错),然后运行时引擎会在作用域中查找改变量,如果找到了就进行赋值。

  作用域嵌套

    作用域是怎么形成的呢?简单来讲就是执行环境所决定的,每一个执行环境都有一个与之关联的变量对象,环境内的所有变量和函数都保存在这个对象中,在全局环境下执行保存在全局的变量对象中叫全局作用域,在函数内的变量保存在函数内部的变量对象构成局部作用域。当代码在一个环境中执行时,会创建变量对象的一个作用域链,作用域链的前端始终都是当前代码所在环境的变量对象中。编译器在查找变量时就是沿着作用域链一级一级地搜索标识的过程,直到全局执行环境也就是全局作用域为止。当一个作用域嵌套在另一个作用域中,就发生了作用域嵌套,因此在当前作用域中无法找到某个变量时,引擎就会沿着作用域链在外层嵌套的作用域中查找,知道找到该变量或者在作用域链顶端(全局作用域)为止。如下:

function foo(a){
console.log(a+b);
}
var b = 2;
foo(2); //

这段代码中,引擎首先会在foo函数中问foo的作用域,你见过b吗?foo作用域:没见过,滚犊子。然后引擎沿着作用域链往上爬,爬到了全局作用域中,然后问:全局作用域大哥你见过b吗?全局作用域:嗯 我见过,给你吧。

嵌套作用域规则很简单,就是在当前作用域开始,一级一级地向上查找。直到抵达最外层全局作用域,查找过程就会停止!

之前说过,变量在赋值操作前总是会先查找然后再赋值,如果在非严格模式下,查找不到所要赋值的变量,全局作用域中会隐式的创建一个具有该名称的变量并返回给引擎。如下:

function foo(a){
console.log(a+b);
b = a;
}
foo(2); //

好久之前写的,好像我是在抄书,照本宣科吗?哈哈

  

    

    

理解JavaScript中的作用域的更多相关文章

  1. 深入理解JavaScript中的作用域和上下文

    介绍 JavaScript中有一个被称为作用域(Scope)的特性.虽然对于许多新手开发者来说,作用域的概念并不是很容易理解,我会尽我所能用最简单的方式来解释作用域.理解作用域将使你的代码脱颖而出,减 ...

  2. 理解JavaScript中的作用域和上下文

    JavaScript对于作用域(Scope)和上下文(Context)的实现是这门语言的一个非常独到的地方,部分归功于其独特的灵活性. 函数可以接收不同的的上下文和作用域.这些概念为JavaScrip ...

  3. 理解JavaScript中的作用域链

    理解了作用域链,闭包就不难理解了,所以本文主要谈一谈我对作用域链的理解.   关于JavaScript中变量的作用域,全局变量在程序中始终都有定义.局部变量在声明它的函数体内以及其内部所嵌套的函数内始 ...

  4. 深入理解JavaScript中的作用域、作用域链和闭包

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/qappleh/article/detai ...

  5. 理解 JavaScript 中的 this

    前言 理解this是我们要深入理解 JavaScript 中必不可少的一个步骤,同时只有理解了 this,你才能更加清晰地写出与自己预期一致的 JavaScript 代码. 本文是这系列的第三篇,往期 ...

  6. 深入理解javascript中执行环境(作用域)与作用域链

    深入理解javascript中执行环境(作用域)与作用域链 相信很多初学者对与javascript中的执行环境与作用域链不能很好的理解,这里,我会按照自己的理解同大家一起分享. 一般情况下,我们把执行 ...

  7. JavaScript中的作用域

    很多(JavaScript)开发者都在讨论"作用域",但它是什么?它们在JavaScript中的任何地方!我发现很多年轻的开发者不知道作用域是什么.他们中大多数人可以用jQuery ...

  8. 理解JavaScript中的原型继承(2)

    两年前在我学习JavaScript的时候我就写过两篇关于原型继承的博客: 理解JavaScript中原型继承 JavaScript中的原型继承 这两篇博客讲的都是原型的使用,其中一篇还有我学习时的错误 ...

  9. 深入理解JavaScript中创建对象模式的演变(原型)

    深入理解JavaScript中创建对象模式的演变(原型) 创建对象的模式多种多样,但是各种模式又有怎样的利弊呢?有没有一种最为完美的模式呢?下面我将就以下几个方面来分析创建对象的几种模式: Objec ...

随机推荐

  1. POJ 3278 Catch That Cow(BFS,板子题)

    Catch That Cow Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 88732   Accepted: 27795 ...

  2. Linux-vmware tools安装与cdrom挂载(转)

    昨天想直接复制虚拟机centos系统中命令行的内容到主机的txt文档上进行保存,发现不能实现虚拟机与主机之间的直接通讯,后来查资料发现原来是由于我的虚拟机没有安装vwmare tools的缘故. 一个 ...

  3. 关于vue的使用计算属性VS使用计算方法的问题

    在vue中需要做一些计算时使用计算属性和调用methods方法都可以达到相同的效果,那么这两种使用方式的区别在哪里: <div id="example"> <p& ...

  4. Fiddler显示服务器IP的方法

    Fiddler默认配置中是看不到服务器IP的,接下来简单介绍下在fiddler上也能够看到请求的服务器IP: 1.Fiddler--->Rules--->Customize Rules , ...

  5. python写一个防御DDos的脚本(请安好环境否则无法实验)

    起因: 居然有ddos脚本,怎么可以没防御ddos的脚本! 开始: 1.请执行 install.py安装好DDos-defalte,会在root目录下多出这个文件夹 代码: 2.然后执行fyddos. ...

  6. 算法-java代码实现计数排序

    计数排序   第10节 计数排序练习题 对于一个int数组,请编写一个计数排序算法,对数组元素排序. 给定一个int数组A及数组的大小n,请返回排序后的数组. 测试样例: [1,2,3,5,2,3], ...

  7. phpstorm 怎么实现分屏展示

  8. Apache、IIS、Nginx等绝大多数web服务器,都不允许静态文件响应POST请求,否则会返回“HTTP/1.1 405 Method not allowed”错误。

    例1:用Linux下的curl命令发送POST请求给Apache服务器上的HTML静态页 [root@new-host ~]# curl -d 1=1 http://www.sohu.com/inde ...

  9. [SinGuLaRiTy] NOIP模拟题 by liu_runda

    [SinGuLaRiTy-1046] Copyright (c) SinGuLaRiTy 2017. All Rights Reserved. 题目名称 兔子 被子 蚊子 源程序文件名 rabbit. ...

  10. jQuery——动态给表格添加序号

    摘录自:http://www.cnblogs.com/picaso/archive/2012/10/08/2715564.html 很多时候遇到需要对表格动态操作,而且一般都会有表格的序号,但是有时候 ...