JavaScript 1、 ES6 声明变量,做用域理解

// JavaScript
/*
* =========================================================
*
* 编译原理
* 尽管一般将 JavaScript 归类为“动态”或“解释执行”语言,但事实上它是一门编译语言。 这个事实对你来讲可能显而易见,也可能你闻所未闻,取决于
* 你接触过多少编程语言,具备多少经验。但与传统的编译语言不一样,它不是提早编译的,编译结果也不能在分布式系 统中进行移植。
*
* 分词/词法分析(Tokenizing/Lexing)
* 这个过程会将由字符组成的字符串分解成(对编程语言来讲)有意义的代码块,这些代 码块被称为词法单元(token)。
* 例如,考虑程序var a = 2;。这段程序一般会被分解成 为下面这些词法单元:var、a、=、2 、;。空格是否会被看成词法单元,取决于空格在
* 这门语言中是否具备意义。
*
*
* 解析/语法分析(Parsing)
* 这个过程是将词法单元流(数组)转换成一个由元素逐级嵌套所组成的表明了程序语法 结构的树。这个树被称为“抽象语法树”
* (Abstract Syntax Tree,AST)。 var a = 2; 的抽象语法树中可能会有一个叫做 VariableDeclaration 的顶级节点,接下 来是一个叫做
* Identifier(它的值是 a)的子节点,以及一个叫做 AssignmentExpression 的子节点。AssignmentExpression 节点有一个叫做
* NumericLiteral(它的值是 2)的子 节点。
*
* 代码生成
* 将 AST 转换为可执行代码的过程称被称为代码生成。这个过程与语言、目标平台等息 息相关。 抛开具体细节,简单来讲就是有某种方法能够
* 将 var a = 2; 的 AST 转化为一组机器指 令,用来建立一个叫做 a 的变量(包括分配内存等),并将一个值储存在 a 中。 * * * * JavaScript 三大实现构成 * 1、ECMAScript:JavaScript的核心 * 2、DOM(document object model):把整个页面映射为一个多节点的结构,借助DOM提供的API,能够轻松的对节点增长,删除,替换。 * 3、BOM(browser object model):能够控制浏览器显示的页面之外的东西,如:窗口和框架等。 * * WEB浏览器只是ECMAScript的宿主环境之一,其次还有:Node,Adobe Flash等。 * * JavaScript 中顶层对象 * 一、window对象,它是JavaScript的最顶层对象,其它的BOM对象都是windows对象的属性; * 二、document对象表示浏览器中加载页面的文档对象; * 三、location对象包含了浏览器当前的URL信息; * 四、navigator对象包含了浏览器自己的信息; * 五、screen对象包含了客户端屏幕及渲染能力的信息; * 六、history对象包含了浏览器访问网页的历史信息。 * * 变量:声明的变量是存在与栈内存(先进后出),引用存放在堆内存(先进先出),。 * 1.栈内存:存储变量,包括引用变量,存储在RAM中,是先进后出的,而且像列表同样的由上而下排列,向下则是增长一个变量,向上则是释放一个变量。 * 2.堆内存:存储对象,存储在RAM中,是先进先出,像集合同样的一个内存池。 * * 做用域:定义存储变量的一套规则,LHS(为变量赋值) 和 RHS(获得某某的值),并在的编译时,编译器和引擎都须要和做用域 * 一次次的沟通并确认做用域中是否存在此变量。 * * 当一个html文件调用多个js文件时(只有一个窗口),使用var定义变量时:它们都属于同一个做用域,而且window这种顶层对象中时共用的。 * * 当使用LET定义变量时,不会出如今顶层对象(window)中,ES6引入了块的概念,因此let定义的变量时存储在当前块(暂存死区)中,在此块以外的地方 * 都将不能使用,而且在let以前使用let定义的变量将直接抛出 ReferenceError错误。 * * var定义的变量将出如今顶层对象(window)中,var定义变量时,会有一个变量提高的功效:即的var定义变量以前可使用,但值却时undefined,由于 * 在编译的过程当中会把变量声明提高到当前做用域的最上方,即:var a = 10; 在编译时,var a; 而后是 a = 10;变量赋值并无作提高,只是声明被提高了, * 这是由于:JavaScript 在语言设计时,易与实现。 * * const定义的值变量,并不能更改其值。当定义引用变量时,其值是能够更换的,可是引用是不能更换,不然都将抛出TypeError * * *不使用标示符声明变量* * 不使用标示符声明变量,相似var声明变量同样,有一个特性不一样,在非严格模式下,当在做用域对变量进行RHS(获得某某的值),若是直至全局做用域找不到, * 将会抛出ReferenceError,若是在做用域对变量进行LHS(为某某变量赋值),直至全局做用域还找不到变量,全局做用域中就会"建立一个"具备该名称的 * 全局变量并将其返还给引擎。 * * *严格模式* * 与松散模式相比,其中一个不一样的行为是严格模式禁止自动或隐式地建立全局变量,LHS查询失败时,会与RHS同样抛出ReferenceError。 * * Error * ReferenceError 同做用域判别失败相关,而 TypeError 则表明做用域判别成功了,可是对 结果的操做是非法或不合理的。 * * 函数:定义函数分为两种,1.function a(){}, 2.var a = function(){},前者是'函数声明',后者是'函数表达式' * 1.函数声明会有"提高"的功效,函数表达式则"没有提高"的功效。 * 2.函数声明的"提高"功效,要优先与变量的提高,即:在同一个做用域中,函数声明提高优先级大于变量优先级。 * 推荐使用1声明函数,在ES6的出现,可使用 async 定义函数,也是推荐使用这种。 * * * * ========================================================= * */// let 定义的值不会在javascript顶层出现,只出如今当前做用域中let a = 20;console.log(this.a,'this.a'); // undefined// var 定义的变量会在顶层出现。var b = 30;console.log(this.b,'this.b'); // 30// 定义的值不会在javascript顶层出现,只出如今当前做用域中const c = 10;console.log(this.c,'this.c'); // undefined// c = 50; // 使用const定义值类型变量时,修改值内容,抛出typeErrorconst d = {a: 1, b: 2};const e = {c: 1};// d = e; // 使用const定义引用类型变量时,修改引用地址,抛出typeErrord.c = 19; // 使用const定义引用类型变量时,能够修改引用对象内容。console.log(d, 'd object'); // 验证经过 Object {a: 1, b: 2, c: 19} "d object"/* * ========================================================= * * JavaScript 做用域嵌套 * 1.查找变量规则 * 引擎从当前做用域中开始查找变量,若是找不到,就向上一级继续查找,当抵达最外层的全局做用域时,不管找到仍是没找到,查找过程都将中止。 * * 2.做用域链 * 做用域链查找变量的规则和做用域嵌套查找变量的方式是同样的。 * * ========================================================= * */// 在foo函数中,找不到f变量时,就会向上级查找变量,在全局做用域中查找到f变量。// function foo(a) {// console.log(a + f,'==a + f');// }// var f = 2;// foo(2);// 对f RHS操做,因此会抛出ReferenceError// function foo(a) {// console.log(a + f, '==a + f');// f = a;// }// foo(2);// 非严格模式下,不使用var let const 等声明变量,对l LHS操做,全局做用域中会对l,建立一个l全局变量变量。// 使用严格模式可验证这个证实function foo(a) { // 'use strict'; l = a; console.log(a + l,'a+b');}foo(2);console.log(this.l,'this.l');
相关文章
相关标签/搜索