有如下代码:

 <body>
<script>
alert(f); function f() {
console.log("fff");
}
var f = 5;
</script>
</body>

不论var f 与function f 的先后顺序如何,该代码执行的结果总是弹出function f 的字符串,为什么呢?像这种函数与变量命名冲突时JS的处理原则又是什么?

在扫描函数声明与变量声明的时候,是先扫描函数声明(function fn()),后扫描变量声明(var a)的;

  • 处理函数声明有冲突,会覆盖;
  • 处理变量声明有冲突,会忽略;

上面代码中,由于先扫描函数声明,所以LexicalEnviroment对象中先存在了 f 指向函数的引用,然后扫描到变量的时候发现变量名冲突,忽略这个变量,所以总是弹出函数字符串。

也就是说,在JS中函数的优先级是高于变量的。相同优先级以后面的为准,不同优先级以级别高的为准。

然后当存在两个同名函数时,会覆盖,所以总是指向后一个函数的,这点就像声明两个同名变量一样。

总结:有如下代码:

     <script>
alert(a);
// alert(b);
alert(f);
alert(g); var a = 5;
b = 6;
alert(b);
function f() {
console.log("fff");
}
var g = function() {
console.log("ggg");
}
alert(g);
</script>

这段代码在预处理阶段,分别扫描函数声明和变量声明,加入到全局对象window中:

 window = {
f: 函数引用,
a: undefined,
g: undefined
}

注意,由于函数 g 是以函数表达式的方式声明的,所以在预处理时会当作一个变量,其值为undefined,所以上面代码执行结果为弹出undefined, f 的字符串表示, undefined

然后走过了var a = 5; b = 6;之后window对象变为:

 window = {
f: 函数引用,
a: 5,
b: 6,
g: undefined
}

所以此时alert(b)弹出6;

因为在JS中不用var声明,直接写的变量默认为全局变量(window的),此时直接不用预处理而直接一步加到全局对象中,预处理的undefined被赋值。

然后走过函数f与函数g的表达式,此时g也指向函数,所以最后alert(g)弹出g的字符串。

JS的解析与执行过程—全局预处理阶段之命名冲突的处理策略的更多相关文章

  1. JS的解析与执行过程—全局预处理阶段之全局词法环境对象

    问题:有如下代码 var a = 1; function pop() { alert(a); var a = 5; } pop();//执行结果,弹出undefined 这段代码的执行结果为undef ...

  2. JS的解析与执行过程—函数预处理

    声明:之所以分为全局预处理与函数预处理,只是为了理解方便,其实在实际运行中二者是不分先后的. 函数预处理阶段与全局预处理的差别: 函数每调用一次,就会产生一个LexicalEnviroment对象,在 ...

  3. JS的解析与执行过程

    JS的解析与执行过程 全局中的解析和执行过程 预处理:创建一个词法环境(LexicalEnvironment,在后面简写为LE),扫描JS中的用声明的方式声明的函数,用var定义的变量并将它们加到预处 ...

  4. js全局的解析与执行过程

    先看下面实例的执行结果: alert(a);//undefined alert(b);//报错 alert(f);//输出f函数字符串 alert(g);//undefined var a = 1; ...

  5. JS引擎线程的执行过程的三个阶段(二)

    继续JS引擎线程的执行过程的三个阶段(一) 内容, 如下: 三. 执行阶段 1. 网页的线程 永远只有JS引擎线程在执行JS脚本程序,其他三个线程只负责将满足触发条件的处理函数推进事件队列,等待JS引 ...

  6. JS引擎线程的执行过程的三个阶段(一)

    浏览器首先按顺序加载由<script>标签分割的js代码块,加载js代码块完毕后,立刻进入以下三个阶段,然后再按顺序查找下一个代码块,再继续执行以下三个阶段,无论是外部脚本文件(不异步加载 ...

  7. js函数的解析与执行过程

    function f(a,b,c){ alert(a);//函数字符串 alert(b); var b = 5; function a(){ } } f(1,2); //预处理 lexicalEnvi ...

  8. openWRT自学---基于backfire版本,分析其Make命令的执行过程和各阶段的主要产物

    准备阶段:从SVN下载backfire的编译环境(位置是:svn co svn://svn.openwrt.org/openwrt/branches/backfire),然后按照openWRT的要求, ...

  9. js的解析--预处理(三)

    js的解析与执行过程  分全局  {预处理阶段和执行阶段}  函数{预处理函数和执行阶段}   1/创建词法环境(环境上下文) LexicalEnvironment   === window { } ...

随机推荐

  1. gps 地图

    http://www.cnblogs.com/sylvanas2012/p/5342530.html http://blog.csdn.net/ma969070578/article/details/ ...

  2. 养活一款APP要“烧”多少钱?

    Duang!又一款APP刷爆朋友圈.大片范儿的电影截图.意味深长的经典对白均出自一款名为“足记”的APP. 足记团队刚于去年8月完成天使期融资,投资方是光速创投和紫辉创投,目前正准备A轮融资.且近一周 ...

  3. leetCode(38):Lowest Common Ancestor of a Binary Search Tree

    Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given nodes in the BS ...

  4. Android体验高扩展艺术般的适配器

    前言 本篇文章带大家体验一下一种具有扩展性的适配器写法. 这个适配器主要用于Item有多种的情况下.当然仅仅有一种类型也是适用的 实现 毫无疑问我们要继承BaseAdapter,重写getCount, ...

  5. bzoj1296: [SCOI2009]粉刷匠(DP)

    1296: [SCOI2009]粉刷匠 题目:传送门 题解: DP新姿势:dp套dp 我们先单独处理每个串,然后再放到全局更新: f[i][k]表示当前串枚举到第i个位置,用了k次机会 F[i][j] ...

  6. 转】关于cgi、FastCGI、php-fpm、php-cgi

    首先,CGI是干嘛的?CGI是为了保证web server传递过来的数据是标准格式的,方便CGI程序的编写者. web server(比如说nginx)只是内容的分发者.比如,如果请求/index.h ...

  7. JMeter使用碰到的问题

    1.创建http请求 使用threadGroup-->add-->sampler--http request 2.使用计数器 使用threadGroup-->add-->con ...

  8. vue子组件使用指令 同时绑定v-model 指令没有作用

    //这里直接上代码 <!DOCTYPE html> <html lang="en"> <head> <meta charset=" ...

  9. vue2.0 兄弟组件数据传递方法

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  10. vcenter server appliance 5.5 管理中心 linux 版本的部署

    本文选自通过ovf模板部署: 需要下面两个文件即可: 打开vsphere client 登录到你安装了exsi5.5的物理机上面: 点击文件---> 部署ovf模板  ---->选择你的模 ...