很久以前遇到过一个面试题目,的的确确是面试官问我的问题,下面是这个问题的代码部分。由于年少无知,没有回答上,被无情pass了。

var u ='hello world';
;(function(){
alert(u);
var u = 'bonjour la monde';
})();
//请问alert的结果是什么?.

一开始毫不犹豫地想到 alert出来的是hello world; 面试官一脸无奈看着我,耸耸肩,我就大概知道被鄙视了。其实结果是undefined,但是一直没想通这样一个结果。后来才明白,JavaScript解析过程分为两个阶段,一个是预解析阶段,另外一个就是执行阶段。

执行阶段我们应该都很明白是什么意思

var u = 'hello world';
alert(u);

这段代码的结果是在浏览器中弹出出hello world不错,很简单,同样简单的还有下面的代码

alert(u);
var u = 'hello world';

结果是undefinded。因为u是在alert之后初始化的。所以按照从上到下的执行顺序来说,这样的结果是我们能够接受的。那么下面的代码呢?

u();
function u() {
alert('hello world');
}

结果是alert弹出hello world;这是为什么呢?u()明显地是在function函数上面先调用的,为什么函数能够执行呢?

其实在执行代码之前,浏览器会对js代码做预解析,解析的原则是这样的: 对该环境内用var声明变量进行提升到顶部的动作,并给它一个初始值undefined,同样,浏览器也会对function做提升动作,但是值是function返回的值,而不是undefined。并且按照命名唯一的原则,会将后声明的函数覆盖之前声明的同名函数上。如果你对上述说明不是很明白,我们可以换一种说法:浏览器在刷新的时候会悄悄地去执行。界面的js代码,不过它的执行方式是把所有在环境(window 或者 function)内声明的var 变了全部置顶并初始化为undefined。所以我们一开始面试官出题的代码在预解析之后可以等同于以下代码。

var u = 'hello world';
;(function(){}
var u;//或者var u = undefined;
alert(u);
u = 'bonjour la monde';
})();

有两个变量u,第一个是全局变量u,它是在window这个大环境内声明的,第二个是局部变量,它是在匿名函数function内声明的,因为匿名函数内包含着一个块级作用域,所以我们也可以说匿名函数内包含着一个不同于window的另一个环境。按照我们在上面提到的解析原则,在这个环境内的var变量都会提升到顶部,并且初始化为undefined,所以代码看起来就是上面的那个样子。而解析原则也会对函数提升,但是初始值不是undefined而是该函数本身,也就是说不会改变。那么下面两段代码可以说是同样的效果:

/解析前的函数
(function(){
say();
function say() {
alert('hello world');
}
});
//解析后的同效函数
(function(){
var say = function() {
alert('hello world');
}
say();
});

解析原则还包括对同名函数的覆盖,下面两段代码可以说明解析前后的状态。

//预解析前
(function () {
function say() {
alert('hello world');
} say() function say() {
alert('bonjour la monde');
}
})
//解析后的等效函数
(function(){
var say = function() {
alert('hello world')
}
var say = function() {
alert('bonjour monde')
} say();
});

现在,相信你应该对js的预解析过程有清楚的了解了。需要注意的是,用var和函数命名(function someFun())的方式声明一个函数都没有问题,这取决与项目的需要或者代码的规范或者个人的喜好,但是遇到以上的问题比如用var声明,那么在此之前你是不能够调用它的,而用function name() 方式命名,在同一个环境或者作用域内,你可以在任何地方调用它。

javascript的执行和预解析的更多相关文章

  1. javascript预解析和作用域

    JavaScript解析过程分为两个阶段: 一是:编译阶段.就是JavaScrip预解析阶段,在这个阶段JavaScript解析器将完成把JavaScript脚本代码转换到字节码; 二是:执行阶段.在 ...

  2. js 预解析

    前言 JavaScript是解释型语言是毋庸置疑的,但它是不是仅在运行时自上往下一句一句地解析的呢? 事实上或某种现象证明并不是这样的,通过<JavaScript权威指南>及网上相关资料了 ...

  3. JS预解析与变量提升

    预解析 JavaScript代码的执行是由浏览器中的JavaScript解析器来执行的.JavaScript解析器执行JavaScript代码的时候,分为两个过程:预解析过程和代码执行过程 预解析过程 ...

  4. JavaScript-----11.预解析

    1.预解析 1.1引子 //1问 console.log(num);//报错 num未定义 //2问 console.log(num); //undefined 未报错 var num = 10; / ...

  5. 第112天:javascript中函数预解析和执行阶段

    关于javascript中的函数:  1.预解析:把所有的函数定义提前,所有的变量声明提前,变量的赋值不提前  2.执行 :从上到下执行,但有例外(setTimeout,setInterval,aja ...

  6. javaScript中的小细节-script标签中的预解析

    首先介绍预解析,虽然预解析字面意思很好理解,但是却是出坑出的最多的地方,也是bug经常会有的地方,利用好预解析的特性可以解决很多问题,并且提高代码的质量及数量,浏览器在解析代码前会把变量的声明和函数( ...

  7. js的预解析和代码执行相关规则

    JavaScript解析过程分为两个阶段,一个是编译阶段,另外一个就是执行阶段. 1.编译阶段:又称为预解析阶段,在这个阶段JavaScript解释器将完成把JavaScript脚本代码转换到字节码. ...

  8. Javascript预解析、作用域、作用域链

    最近在看js的一些资料,总结一下昨晚看到的js作用域方面的知识,不准确的地方希望留言指正! 先看片段js代码如下: < script type="text/javascript&quo ...

  9. JavaScript函数之作用域 / 作用链域 / 预解析

    关于作用域和作用链域的问题,很多文章讲的都很详细,本文属于摘录自己觉得对自己有价值的部分,留由后用,仅供参考,需要查看详细信息请点击我给出的原文链接查看原文件 做一个有爱的搬运工~~ -------- ...

随机推荐

  1. Win7(32bit)下Qt5.5.0和OpenCV2.4.9环境的搭建

    之前一直基于Windows平台(Win 7 32bit)使用VS2010做OpenCV的开发,现在开始学习在Windows 下使用Qt做OpenCV的开发.本文主要讲述Windows平台下(Win 7 ...

  2. HTML可编辑的select

    HTML可编辑的select实现原理还是用select和input伪装成的! <!DOCTYPE html PUBLIC "-//W3C//Dth XHTML 1.0 Transiti ...

  3. en_windows_10_multiple_editions_version_1511_x64.iso

    好久没折腾电脑了,这几天在E盘装了个64位Windows 10 TH2 专业版,从MSDN官网下载的英文原版镜像,用kms10未能激活,一看日志文件,说我这是零售版,后面就关掉了什么监听端口,然后就完 ...

  4. C#高级--通过类来理解学习委托

    namespace classanddelegate { class Program { static void Main(string[] args) { //这是类的实例化 Test test = ...

  5. Highchart使用json格式数据lineDemo

    <html> <head> <title>Highcharts Example</title> <script type="text/j ...

  6. 慕课网Java高并发秒杀学习

    课程地址:http://www.imooc.com/learn/587 一个很好:spring,springMVC,mybatis,bootstrap,jQuery,mysql,Restful学习案例 ...

  7. Everything搜索结果显示0 Object

    比较过windows本身的文档搜索功能,Everything的本地文档搜索能力简直令人咋舌,更逆天的是软件本身体积很小. 问题:打开everything时,文件列表消失,软件下方信息为0 object ...

  8. jsp页面格式时间yy-mm-dd

    这个问题把我花了1小时都没弄出来  各种报错  还是最后同学告知才知道的. 导入  :<%@ taglib uri="http://java.sun.com/jsp/jstl/func ...

  9. 小清新cygwin,正在诞生中

    正文保留. 评论记录点滴.最后汇总.

  10. gulp 配置前端项目打包

    项目发布时,需要对项目js文件进行压缩,混淆,连接等操作以减小项目http请求,加快访问. gulpjs.com中有很多插件可以用来配置打包部署. 需要用的常用插件有: gulp-jsmin  压缩j ...