JS引擎

编译与执行

  Javascript引擎会在词法分析和代码生成阶段对运行性能进行优化,包含对冗余元素进行优化(例如对语句在不影响结果的情况下进行重新组合)。

  对于Javascript来说,大部分情况下编译发生在代码执行前的很短时间内,涉及的概念有引擎、编译器、作用域。

  变量声明例如var a = 2这条表达式,编译阶段会先查询作用域是否有同名变量,如果有就忽略声明(仅仅忽略var的声明),继续编译。如果没有,会在当前作用域的变量集合中创建一个变量,命名为a。

    {
//编译阶段找不到a 执行var a
var a = 1;
//运行阶段执行 a = 1
console.log(a); //
//编译阶段找到了变量a 忽略此条语句
var a = 2;
//运行阶段执行 a = 2
console.log(a); //
}

LHS查询与RHS查询

  当变量被使用时,会进行查询操作,例如赋值操作a = 1是LHS查询,另外一种称为RHS查询。

  简单理解就是,对于赋值操作(包括隐性的)为LHS,作为变量进行引用时时RHS查询。

    {
//赋值操作 LHS查询
var a = 1;
function fn(a) {
//进入函数体存在一个隐性的a = 2操作
//log使用RHS查询
console.log(a);
}
//函数调用发生RHS查询 2作为引用传入
fn(2);
}

作用域嵌套  

  一个块或函数嵌套在另一个块或函数中时,就会形成作用域嵌套,在当前作用域无法找到某个变量时,就会在外层作用域继续查找,直到找到该变量;或者没找到,抛出一个错误,查询停止。

词法作用域

  作用域有两个工作模型,一种是词法作用域,另一种叫动态作用域。

    //全局作用域
//包含f1
function f1(a) {
var b = a * 2;
//f1的作用域
//包含a,b,f2,
function f2(c) {
//f2的作用域
//包含c
console.log(a, b, c); // 2,4,4
}
f2(b)
}
f1(2)

  变量查找会先从最内部的作用域开始查找,找不到会去上一级嵌套的作用域。

  无论函数在哪里被调用,也无论如何被调用,词法作用域都只由函数被声明时所处的位置决定。(闭包)

    function outer() {
//找到后返回a
var a = 1;
//保留对outer作用域中a的引用
function inner() {
//被调用时开始查询变量a
return a;
}
return inner();
} function f1() {
//outer作用域决定于声明处
//所以不会查找到f1的a
var a = 2;
//在这里调用词法作用域依然不会变
outer();
}
f1(); //

  顺便讲一下闭包为什么会改变变量的生命周期,闭包需要两个条件。

  1、外部函数内部有另外一个函数,并对外部函数的某个变量保持了引用。

  2、外部函数提供一个内部函数的访问接口。

  而内部函数对外部作用域的引用保持就叫闭包。

  生命周期的问题还要提到GC回收问题,一般常见的回收算法有两种:引用计数算法、标记算法,由于引用计数会出现循环引用问题,这里以标记算法举例简单讲一下。标记算法会将代码构建成类似于DOM树之类的结构,根节点为window,第一轮先开始向下遍历,可以被根节点引用的变量上一个标记(假设为false)。遍历完后,第二轮开始清除操作,所有标记为true将会被垃圾回收。看不懂的话,还是看代码注释吧。

    function fn1() {
var a = 1;
//闭包条件1
function fn2() {
a = a + 1;
return a;
}
//闭包条件2
return fn2;
}
var fn = fn1();
// a变量并没有被回收
// window.fn => fn2 => a 可以获取到a 保留
console.log(fn()); //
console.log(fn()); //
function fn3() {
var b = 1;
b++;
//此函数没用
function fn4() {
console.log(b);
}
return b;
}
//window.fn3 => ??? b无法被引用 消除
console.log(fn3()); //
console.log(fn3()); //2 被回收了并再次初始化

   另外,可以通过eval和with语法强行修改作用域,但并不推荐使用,主要是性能方面的问题。因为引擎在编译时会对词法作用域进行分析优化,保证代码运行时能更快的找到对应的变量,但是如果有eval问题就不一样了,无法保证会传入什么代码,有可能会影响现有的作用域导致优化失败,所以引擎可能会根本不优化,

读书笔记-你不知道的JS上-词法作用域的更多相关文章

  1. 读书笔记-你不知道的JS上-函数作用域与块作用域

    函数作用域 Javascript具有基于函数的作用域,每声明一个函数,都会产生一个对应的作用域. //全局作用域包含f1 function f1(a) { var b = 1; //f1作用域包含a, ...

  2. 读书笔记-你不知道的JS上-this

    关于this 与静态词法作用域不用,this的指向动态绑定,在函数执行期间才能确定.感觉有点像C++的多态? var a = 1; var obj = { a: 2, fn: function() { ...

  3. 读书笔记-你不知道的JS上-闭包与模块

    闭包定义 当函数可以记住并访问所在的词法作用域时,就产生了闭包,即使函数是在当前词法作用域之外执行. 看一段最简单的闭包代码: function foo() { var a = 2; //闭包 fun ...

  4. 读书笔记-你不知道的JS上-对象

    好想要对象··· 函数的调用位置不同会造成this绑定对象不同.但是对象到底是什么,为什么要绑定他们呢?(可以可以,我也不太懂) 语法 对象声明有两个形式: 1.字面量 => var obj = ...

  5. 读书笔记-你不知道的JS上-声明提升

    变量声明提升 Javascript代码一般情况下是由上往下执行的,但是有些情况下不成立. a = 2; //变量声明被提升在当前作用域顶部 var a; console.log(a); console ...

  6. 读书笔记-你不知道的JS上-混入与原型

    继承 mixin混合继承 function mixin(obj1, obj2) { for (var key in obj2) { //重复不复制 if (!(key in obj1)) { obj1 ...

  7. 《你不知道的JavaScript》读书笔记(二)词法作用域

    JavaScript 采用的是 词法作用域 的工作模型. 定义 词法化:大部分标准语言编译器的第一个工作阶段叫词法化(单词化),这个过程会对源代码中的字符进行检查,如果是有状态的解析过程,还会赋予单词 ...

  8. 读书笔记-你不知道的JavaScript(上)

    本文首发在我的个人博客:http://muyunyun.cn/ <你不知道的JavaScript>系列丛书给出了很多颠覆以往对JavaScript认知的点, 读完上卷,受益匪浅,于是对其精 ...

  9. 读书笔记-你不知道的JS中-promise

    之前的笔记没保存没掉了,好气,重新写! 填坑-- 现在与将来 在单个JS文件中,程序由许多块组成,这些块有的现在执行,有的将来执行,最常见的块单位是函数. 程序中'将来'执行的部分并不一定在'现在'运 ...

随机推荐

  1. 关于memcached的那些事儿

    一.前言 目前,memcached + mysql的这种存储组合,被广泛地应用到“读多写少”的应用场景上.那么在使用memcached的时候,我们需要注意哪些问题呢? 下面我们来探讨下使用memcac ...

  2. 在java中使用MongoDB数据库

    Java 安装 要想在 Java 程序中使用 MongoDB,需要先确定是否安装了 MongoDB JDBC 驱动,并且要在机器上安装了 Java.查看 Java 教程来确保在机器上安装好 Java. ...

  3. js两个叹号的使用

    1.浏览器判断空和未定义以及零时返回的值如下: alert(undefined)  //undefined alert(null)  //null alert(0)  //0 2.有时为了便于下一步判 ...

  4. oracle pl/sql 函数

    函数用于返回特定的数据,当建立函数时,在函数头部必须包含return子句.而在函数体内必须包含return语句返回的数据.我们可以使用create function来建立函数. 1).接下来通过一个案 ...

  5. 深入浅出AQS之独占锁模式

    每一个Java工程师应该都或多或少了解过AQS,我自己也是前前后后,反反复复研究了很久,看了忘,忘了再看,每次都有不一样的体会.这次趁着写博客,打算重新拿出来系统的研究下它的源码,总结成文章,便于以后 ...

  6. 编码格式简介:ASCII码、ANSI、GBK、GB2312、GB18030和Unicode、UTF-8,BOM头

    编码格式简介:ASCII码.ANSI.GBK.GB2312.GB18030和Unicode.UTF-8,BOM头 二进制: 只有0和1. 十进制.十六进制.八进制: 计算机其实挺笨的,它只认识0101 ...

  7. VirtualBox安装linux mint教程

    准备工作: 1.VirtualBox安装包,官方下载页面. 2.linux mint镜像iso文件,官方下载页面. 安装过程: 1.打开VirtualBox后点击新建,在弹出界面选择专家模式,类型选择 ...

  8. Spring 5:以函数式方式注册 Bean

    http://www.baeldung.com/spring-5-functional-beans 作者:Loredana Crusoveanu 译者:http://oopsguy.com 1.概述 ...

  9. OpenJudge_1321:棋盘问题

    题目描述 在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别.要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆 ...

  10. 【POJ】3090 Visible Lattice Points(欧拉函数)

    Visible Lattice Points Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7705   Accepted: ...