javascript代码是如何执行的呢,分为六个步骤(就像把大象装进冰箱总共分几步?):

  第一步:载入第一个js代码段(注:script标签对内的代码或是引用js代码,这也说明js并不是一行一行(单纯意义上的自上而下)执行的,而是一段一段执行的)。

  第二步:词法分析、语法分析,如果这时有语法错误,解释器便会终止执行该代码并抛出语法(Syntax Error)的错误,并转达到第五步。

  第三步:对段内的var和function做预解析,这一步不会报错。

  第四步:执行代码。

  第五步:如果还有代码段,则载入下个代码,跳到第二步接着来。

  第六步:结束。

流程图为:

  首先:在js解释器启动时或web浏览器加载新的页面时,会自动创建一个全局对象,并给它定义一组初始属性,在客户端javascript中,window便是这个全局对象,它有一个window属性引用自身,代替this来引用全局对象;如果代码中声明了一个全局变量,那么这个全局变量便是全局对象中的一个属性(查看方式为在firefox或chrome中,按F12键调出控制台,在控制台中输入for(var i in window) {console.log(i + ' ' + window[i])},便可看到初始属性)。全局域(window)下所有的js代码,可以看成一个被自动执行的“匿名方法”,而“匿名方法”内的方法,则需要显示调用才被执行。例如:

(function () {
    function a() {
        console.log('我是a方法,需要显示调用才执行');
    }
    console.log('我是匿名方法内的,被自动执行了');
    a();
})()  

其次:上述流程概括就是解析和执行两个阶段。

  第一阶段:通过词法分析、预解析生成语法分析树。

  第二阶段:执行。执行某个具体的function时,js解释器会为它创建一个执行环境(ExecutionContext)和活动对象(ActiveObject)。

之前描述过了词法分析的流程,这里就不过多的分析了,直接上图:

下面,直接上题:

if(!('a' in window)){
    var a = 1;
}
alert(a); // undefined;

有的同学就会感到奇怪了,为什么啊,为什么不是1呢,也没见到其他地方声明a啊,所以a属性不在全局域内啊,理应弹出1啊。别急,且听我细细解释。

首先看看上面列出的六个步骤,在第三步js解释器会对代码中的function和var进行预解析,也就是说在碰到var声明时,会把var声明提到顶部,于是上段代码便成了这样

var a;
if(!('a' in window)){
    a = 1;
}
alert(a); // undefined;

关于变量的声明的步骤之前文章中就讲过了,这里就不多说了。

看到这儿,同学们应该不难理解为什么弹出undefined了吧。需要说明的是在js中,对于var a=1;这样代码,其实是分为两步执行的,先声明,再赋值,如果没有赋值,那么a的值便是undefined。

再来第二题:

var a = 1,
    b = function (x) {
        x && b(--x);
    };
alert(a); // 1

这题看上去便比较纠结了吧,定义了个a变量,接着又定义了个有名函数a,这都什么和什么啊。其实完全不必纠结,我改变下写法,同学们便会明白

var a = 1,
    b = function (x) {
        x && b(--x);
    };
alert(a);  

怎么样,再来一题:

function a(x) {
    return x * 2;
}
var a;
alert(a); 

认真看完第一题的同学,会有部分说,这有何难,不就是弹出undefined么,可结果是,真的是那样的么?结果是

function a(x) {
    return x * 2;
}  

  啊,怎么会这样呢,不是说var a,只声明没定义,就是undefined么,为什么会弹出一个函数呢。别急,还是第三步。js解释器会对代码中的function和var进行预解析,那么如果两者同时存在呢,而且都是对同一个a进行声明,那又如何处理?事实上,对于这种情况,js解释器早已考虑到了,当两者同时存在时,函数声明的优先级大于变量声明,而且如果变量只声明而没有赋值的话,便会覆盖它。记住,如果变量声明的同时,也赋值了,那么就不一样了,如:

function a(x) {
    return x * 2;
}
var a = 1;
alert(a);  

这时便会弹出1了。我们再深入点,看看下面的代码:

function a(x) {
    return x * 2;
}
var a = 1;
alert(typeof a);  

这时会弹出number,对,这时函数声明便会被变量声明覆盖。

还没完,再来一题:

function b(x, y, a) {
    arguments[2] = 10;
    alert(a);
}
b(1, 2, 3);  

这题主要是考察了方法内的arguments对象,这个是类数组的对象,真实记录了方法的形参个数和长度,但记住,它不是数组,只是个长的像数组的对象

这个问题在之前的文章里也谈过了。

var argumengts = {0:1, 1:2, 2:3, length:3}  

看到这,结果弹出什么就一目了然了吧。

还有一题:

function a() {
    alert(this);
}
a.call(null);  

  这题我觉得主要考察了两个知识点,this的指向谁和call如何把this强制改变并指向谁。在上面的几个关键概念中,解释了js词法作用域是在定义时决定而不是执行时决定,因此可以静态分析。那么我们就来分析下,撇开下面的a.call(null),方法a是在全局下定义的,因此在全局作用域下调用a,this便会指向调用它的那个对象window,于是

function a() {
    alert(this); // 指向window
}
a() // 在全局域内等同于window.a()  

那么a.call(null)呢,this指向null,那么弹出什么呢?在ECMAScript262中,如果call,apply方法中第一个参数传入null,等同于传入window,因此和上述代码一样。 

javascript --- 再谈词法分析的更多相关文章

  1. JavaScript 再谈闭包

    之前有整理过一版关于闭包的概念,但感觉思路不是很清晰,是临时想起一些例子来讲的,今天再次来讲一下闭包. 闭包: 函数嵌套函数,内部函数可以引用外部函数的参数和变量 function aaa(a){ v ...

  2. 再谈JavaScript的数据类型问题

    JavaScript的数据类型问题已经讨论过很多次了,但许多人还有许多书仍然沿用着错误的.混乱的一些观点,所以就再细讲一回. 提及这个讨论的原因在于argb同学在我的MSN博客上的一段回复,又更早的起 ...

  3. 再谈JSON -json定义及数据类型

    再谈json 近期在项目中使用到了highcharts ,highstock做了一些统计分析.使用jQuery ajax那就不得不使用json, 可是在使用过程中也出现了非常多的疑惑,比方说,什么情况 ...

  4. 再谈angularJS数据绑定机制及背后原理—angularJS常见问题总结

    这篇是对angularJS的一些疑点回顾,是对目前angularJS开发的各种常见问题的整理汇总.如果对文中的题目全部了然于胸,觉得对整个angular框架应该掌握的七七八八了.希望志同道合的通知补充 ...

  5. 再谈前端HTML模板技术

    在web2.0之前,写jsp的时候虽然有es和JSTL,但是还是坚持jsp.后面在外包公司为了快速交货,还是用了php Smart技术. web2.0后,前端模板技术风行. 代表有如下三大类: Str ...

  6. 再谈DOMContentLoaded与渲染阻塞—分析html页面事件与资源加载

    浏览器的多线程中,有的线程负责加载资源,有的线程负责执行脚本,有的线程负责渲染界面,有的线程负责轮询.监听用户事件. 这些线程,根据浏览器自身特点以及web标准等等,有的会被浏览器特意的阻塞.两个很明 ...

  7. 再谈HTTP2性能提升之背后原理—HTTP2历史解剖

    即使千辛万苦,还是把网站升级到http2了,遇坑如<phpcms v9站http升级到https加http2遇到到坑>. 因为理论相比于 HTTP 1.x ,在同时兼容 HTTP/1.1 ...

  8. 再谈 Go 语言在前端的应用前景

    12 月 23 日,七牛云 CEO & ECUG 社区发起人许式伟先生在 ECUG Con 2018 现场为大家带来了主题为<再谈 Go 语言在前端的应用前景>的内容分享. 本文是 ...

  9. 再谈js对象数据结构底层实现原理-object array map set

    如果有java基础的同学,可以回顾下<再谈Java数据结构—分析底层实现与应用注意事项>:java把内存分两种:一种是栈内存,另一种是堆内存.基本类型(即int,short,long,by ...

随机推荐

  1. Silver Cow Party(最短路,好题)

    Silver Cow Party Time Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Su ...

  2. 左倾堆(一)之 图文解析 和 C语言的实现

    概要 本章介绍左倾堆,它和二叉堆一样,都是堆结构中的一员.和以往一样,本文会先对左倾堆的理论知识进行简单介绍,然后给出C语言的实现.后续再分别给出C++和Java版本的实现:实现的语言虽不同,但是原理 ...

  3. 斐波那契堆(三)之 Java的实现

    概要 前面分别通过C和C++实现了斐波那契堆,本章给出斐波那契堆的Java版本.还是那句老话,三种实现的原理一样,择其一了解即可. 目录1. 斐波那契堆的介绍2. 斐波那契堆的基本操作3. 斐波那契堆 ...

  4. Gulp.js - 简单、直观的自动化项目构建工具

    Gulp.js 是一个简单.直观的构建系统.崇尚代码优于配置,使复杂的任务更好管理.通过结合 NodeJS 的数据流的能力,你能够快速构建.通过简单的 API 接口,只需几步就能搭建起自己的自动化项目 ...

  5. iOS-布局-Masonry

    一.说明:demo中的举例视图介绍  UIView        *_blackView;     作为父视图  UIView        *_redView;       与父视图内边距为10   ...

  6. 和为S的连续正数序列

    小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100.但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数).没多久,他就得到另一 ...

  7. [mysql]增加用户 授权 远程登录

    mysql创建用户和授权 1.创建用户: (注意:下面的指令,请在root用户下输入) CREATE USER "用户名" IDENTIFIED BY "密码" ...

  8. js-条件语句、循环语句

    一. 常见条件语句 if 语句 - 只有当指定条件为 true 时,使用该语句来执行代码 if...else 语句 - 当条件为 true 时执行代码,当条件为 false 时执行其他代码 if... ...

  9. 为了去重复,写了一个通用的比较容器类,可以用在需要比较的地方,且支持Lamda表达式

    为了去重复,写了一个通用的比较容器类,可以用在需要比较的地方,且支持Lamda表达式,代码如下: public class DataComparer<T>:IEqualityCompare ...

  10. Qt之QAbstractItemView右键菜单

    一.功能概述 说起右键菜单,之前Qt之自定义QLineEdit右键菜单这篇文章中我已经讲述过3种右键菜单的实现方式,今儿也是在啰嗦一下,针对QListWidget类在定制一下右键菜单,我使用的具体方式 ...