每一个函数都有自己的执行上下文EC(执行环境 execution context),并且每个执行上下文中都有它自己的变量对象VO(Variable object),用于存储执行上下文中的变量 、函数声明 、函数参数,这解释了js如何找到我们定义的函数和变量。并且函数是js中唯一一个能创建出作用域的,注意:for,if()else()不能创建作用域。我们通过以下几个例子说明为什么函数和变量的声明会被前置,为什么匿名函数表达式的不可以在外面调用。

var a = 18;
f1();
function f1(){
var b=9;
console.log(a); //undefined
console.log(b); //
var a = '123';
}

因为在f1中,在此函数还未执行时变量a,b会被提前声明,也就是说可以理解为下面的代码

var a = 18;
f1();
function f1(){
var b;
var a;
b = 9;
console.log(a);
console.log(b);
a = '123';
}

如果想进一步理解内部的运行机制,可以用如下方法:

在此案例中,f1函数的作用域链有两个对象,一个是全局变量对象,一个是f1变量对象。

VO (globalContext) = {

  a: 18,

  f1: <ref to function>

}

1.变量初始化阶段

VO (f1 functionContext) = {

  a: undefined,

  b: undefined

}

2.代码执行阶段

VO (f1 functionContext) = {

  a: undefined,

  b: 9

}

再来两个js经典题

function fn(a){
console.log(a); //function(){}
var a = 2;
function a(){};
console.log(a); //
}
fn(1);

我们知道,在运行fn之前,变量和function都会提前声明,但是function会覆盖变量(在不赋值的前提下),

通过以上案例,我们可以总结如下规律:

VO按照如下顺序填充:
 1.  函数参数  (若未传入,初始化该参数值为undefined)
 2.  函数声明  (若发生命名冲突,会覆盖)
 3.  变量声明  (初始化变量值为undefined,若发生命名冲突,会忽略。)

注意:变量初始化(被声明)和变量根本不在一个变量对象里是有区别的,如果用console打印前者会显示undefined,而后者会报一个"ReferenceError: gg is not defined"。

比如

第一个只有一个全局上下文

VO (globalContext) = {

  fn: <ref to function>

}

因为没有执行fn,所以里面的变量读取不到,第二个通过声明被前置,打印undefined.(只有var的变量才能被前置)

为了让大家充分了解执行上下文,再来一个例子。

function test(a,b){ 
var c = 10; 
function d(){} 
var  e = function _e(){}; 
(function x(){}); 
b = 20;  
}   
test(10);

第一阶段——变量初始化阶段如下       第二阶段——代码执行阶段

     

提示:因为此函数中有形参b,所以在变量初始化阶段会b:undefined,如果没有形参b,会报错 b is not defined。

最后来一个压轴的

alert(a);   //undefined
alert(b);   //undefined
alert(x);   //function x(){}
var x = 10;
alert(x);   // 10
x = 20;
function x(){}
alert(x);   // 20
if (true) {
  var a = 1;
} else {
  var b = true;
}
alert(a);   //1
alert(b);   //undefined

首先声明一点,js是没有块级作用域的,所以if{}else{}里面的变量即使不执行,他们的声明也会前置,所以第一个和第二个alert为undefined,对于第三个alert,因为先是x这个变量前置,然后x又变成了function,前面说过了,函数声明如果发生冲突会覆盖变量声明(可以理解为function的优先级更高),所以第三个弹出function,第四个赋值为10,第五个x=20覆盖x=10,第六个因为执行了if,所以给a赋值弹出1,最后一个还是undefined。

js执行上下文(由浅入深)的更多相关文章

  1. JS执行上下文(执行环境)详细图解

    JS执行上下文(执行环境)详细图解 先随便放张图 我们在JS学习初期或者面试的时候常常会遇到考核变量提升的思考题.比如先来一个简单一点的. console.log(a); // 这里会打印出什么? v ...

  2. 一篇文章看懂JS执行上下文

     壹 ❀ 引 我们都知道,JS代码的执行顺序总是与代码先后顺序有所差异,当先抛开异步问题你会发现就算是同步代码,它的执行也与你的预期不一致,比如: function f1() { console.lo ...

  3. 深入理解js——执行上下文

    什么是"执行上下文"?暂且不下定义,先看一段代码: 第一句报错,a未定义,很正常.第二句.第三句输出都是undefined,说明浏览器在执行console.log(a)时,已经知道 ...

  4. js执行上下文

    js在执行是会有一个“准备工作”: 主要内容有 1.变量.函数表达式——>变量声明,默认赋值为undefined: 2.this——>赋值: 3.函数声明——>赋值: 这三种数据的准 ...

  5. 前端高质量知识(二)-JS执行上下文(执行环境)详细图解Script

    先随便放张图 我们在JS学习初期或者面试的时候常常会遇到考核变量提升的思考题.比如先来一个简单一点的. console.log(a); // 这里会打印出什么? var a = 20; PS: 变量提 ...

  6. js执行上下文栈和变量对象

    JavaScript执行上下文栈和变量对象 JS是单线程的语言,执行顺序肯定是顺序执行,但是JS 引擎并不是一行一行地分析和执行程序,而是一段一段地分析执行,会先进行编译阶段然后才是执行阶段. 例子一 ...

  7. 原型模式故事链(4)--JS执行上下文、变量提升、函数声明

    上一章:JS的数据类型 传送门:https://segmentfault.com/a/11... 好!话不多少,我们就开始吧.对变量提升和函数声明的理解,能让你更清楚容易的理解,为什么你的程序报错了~ ...

  8. js执行上下文与执行上下文栈

    一.什么是执行上下文 简单说就是代码运行时的执行环境,必须是在函数调用的时候才会产生,如果不调用就不会产生这个执行上下文.在这个环境中,所有变量会被事先提出来(变量提升),有的直接赋值,有的为默认值 ...

  9. JS 执行上下文的一次理解

    执行上下文 执行上下文概念 当代码运行时,会产生一个对应的执行环境,在这个环境中,变量会被事先提出来(变量提升),代码从上往下开始执行,就叫做执行上下文. 注:在定义变量是未直接赋值,使用默认值 un ...

随机推荐

  1. 《MFC游戏开发》笔记七 游戏特效的实现(一):背景滚动

    本系列文章由七十一雾央编写,转载请注明出处. http://blog.csdn.net/u011371356/article/details/9344721 作者:七十一雾央 新浪微博:http:// ...

  2. nodejs(一) 简单登录验证 使用mongoose 操作MongoDB

    ---恢复内容开始--- 开发使用webstorm 9  新建nodejs+express 项目 newfarmer 文章目录 配置Mongoose 创建目录及文件 插入数据,POST提交JSON增加 ...

  3. nc命令详解

    NetCat,在网络工具中有“瑞士军刀”美誉,其有Windows和Linux的版本.因为它短小精悍(1.84版本也不过25k,旧版本或缩减版甚至更小).功能实用,被设计为一个简单.可靠的网络工具,可通 ...

  4. [转]WPF 获取程序启动路径

    本文转自:http://hi.baidu.com/lilipangtou/item/f1b7488e3c92c4d05e0ec1ab 在Windows Form程序中,获取自身的启动目录是非常容易的, ...

  5. QTREE3 spoj 2798. Query on a tree again! 树链剖分+线段树

    Query on a tree again! 给出一棵树,树节点的颜色初始时为白色,有两种操作: 0.把节点x的颜色置反(黑变白,白变黑). 1.询问节点1到节点x的路径上第一个黑色节点的编号. 分析 ...

  6. Jquery和JS删除提示

    Jquery <script> $(function () { $('.deletes').click(function () { //提示 if (!confirm('确定呀删除吗?') ...

  7. iOS UIView简单缩放动画

    @interface ViewController () { UIView *animationView; UIButton *button; CGPoint animationPoint; } @e ...

  8. 从数据库里面取值绑定到Ztree

    1.效果图(思路:将数据库表按照一定的格式排序,然后序列化成json字符串,绑定到Ztree上并显示出来) zTree v3.5.16 API 文档 :http://www.ztree.me/v3/a ...

  9. subilme增加对markdown的高亮支持

    sublime2对markdown原生主题支持都没有, 需要通过插件补充 1.插件安装 通过Package Control安装下列插件: Markdown Extended Monokai Exten ...

  10. html5的自定义data-*属性和jquery的data()方法的使用示例

    人们总喜欢往HTML标签上添加自定义属性来存储和操作数据. 但这样做的问题是,你不知道将来会不会有其它脚本把你的自定义属性给重置掉,此外,你这样做也会导致html语法上不符合Html规范,以及一些其它 ...