执行上下文(Execution context)
执行上下文可以认为是 代码的执行环境。
1 当代码被载入的时候,js解释器 创建一个 全局的执行上下文。
2 当执行函数时,会创建一个 函数的执行上下文。
3 当执行 eval()的时候,创建 一个 eval 执行上下文。
# if,for,while 等块不会创建 execution context,从而不会创建 scope。
 
当js解释器开始工作的时候:
1 首先创建一个 执行上下文栈(后进先出)
2 接着创建一个 全局的执行上下文,并放入执行上下文栈中。
3 当在全局上下文中调用一个函数的时候.
    为函数创建一个 执行上下文,
    压入执行上下文栈中。
4 当函数执行结束的时候,位于栈顶的 执行上下文 被弹出。继续执行 新的位于栈顶的执行上下文。
 
这种方式保证了 任意时刻都只有位于栈顶的执行上下文才会被执行,也就是实现了单线程。
 
 
执行上下文创建分成两个阶段:
    创建阶段: 将所有的变量,函数声明以及函数参数 组成一个活动对象(可变对象)
    执行阶段: 解释代码.
 
创建阶段具体做的事情:
1 创建 活动对象VO(variableObject)
2 创建 arguments对象
    检测参数,将参数名作为 key值(arguments对象的所有属性都同时是 VO的属性)
3 检测当前执行上下文中的 函数声明 (function fn(){} 这种叫函数声明)
  每检测到一个函数声明都会在 VO 上添加一个属性,属性名就是函数名。属性值就是函数在内存中的引用
  (
      检测到同名依旧覆盖掉。
  )
4 检测变量声明
  每检测到一个变量声明,就在VO上面添加一个属性,属性名就是变量名,属性值就是 undefined.
  (
      检测到同名就丢弃掉当前。
  )
#34的执行顺序没有关系的,调换顺序也是同样的结果。只要变量声明遇见函数声明,最后留下来的肯定是函数声明。
5 确定当前的this的指向。
 
执行阶段:一行一行解释代码.
 
但是在执行阶段还有一个规律:对于同一个变量的赋值,后面的会覆盖前面的。
 
 
假设有函数:
  function foo(i) {
   var a = 'hello';
   var b = function privateB() {
 
   };
   function c() {
 
   }
}
VO大概长这个样子:
ExecutionContext = {
   variableObject: {
       arguments: {
           0: 22,
           length: 1
       },
       i: 22,
       c: pointer to function c()
       a: undefined,
       b: undefined
   },
   scopeChain: { ... },
   this: { ... }
}
 
 
scope chain
js解释器在创建 执行上下文栈 的时候,会同时创建一个 scope chain。一个单向链表.
当 某个执行上下文的创建阶段的最后:创建的活动对象,会被放到 scope chain的 第一个位置。
在执行上下文的 执行阶段的时候,当需要访问某个变量时,
会首先在 当前的 执行上下文的 VO中查找。如果找不到,就往链表的下一个位置查找,一直到最后一个位置。
# 因为链表是单向的,不能反向查找,这也是为什么,全局的执行上下文不能访问 函数上下文的原因,
就是 函数外部访问不了函数内部的原因.
 
 
1 触发 scope chain 查找的原因只有一个:执行上下文的 执行阶段,遇见了当前 VO中不存在的属性。
所以:
    var a = 'outer';
    function test(a){
        console.log(a);//(1)
        var a = 'inner';
        console.log(a);//(2)
    }
    test();
    // output: undefined,'inner'
因为参数是 a>VO 中有 属性 a,在 (1)的时候,a 的值是 undefined,因为存在a,所以不会触发 scope chain 查找.
如果想要触发,把参数 a 改成其他名字.
# 这个东西,帮助理解一下原理就好,不要在代码中这么干,出了问题都不知道哪里有问题。
 
2 这个用来证明scope chain的查找方向。
    var x = 10;
 
    function foo() {
      alert(x);
    }
 
    (function () {
      var x = 20;
      foo();
    })();
 
3 // 重复的函数声明,后面的会覆盖前面的(函数声明比较霸道一点)
function f(){
    console.log(1);
}
 
f();
function f(){
    console.log(2);
}
f();
 
4 执行阶段的时候的规律,后面的赋值会覆盖前面的同名。
var x = 0;
var f = function(){
    x = 1;
}
f();
alert(x);
function f(){
    x = 10;
}
f();
alert(x);
// output: 1,1
 
 
var b = 10;
(function b(){
  b = 20;
    console.log(b);
})();
// output: function b(){...}
原因:
1 首先进入 全局执行上下文,注册了 b
2 全局执行上下文执行 b = 10
3 进入()();创建的执行上下文,注册了 函数声明 b
4 执行-进入 函数执行上下文
5 注册了b是全局的。
6 输出:
  在函数中找不到,在表达式中找到了,就是 function b(){}
 
如果是:
var b = 10;
(function b(){
  var b = 20;
  console.log(b);
})();
// output:20
 
如果是:
var b = 10;
(function(){
  b = 20;
  console.log(b);
})();
// output:20
 
IIFE和 全局的执行上下文之间还有一层执行上下文,这样才能解释上面的的问题。
 
 
函数表达式&函数声明
    var fn = function(){} // 函数表达式
    function fn(){}  // 函数声明
 
记忆:
vb:使用 var 的 都是 biao 达式
 
区别:
函数声明必须要有函数名,只有函数声明才有 hoisting.
 
 
javascript hositing
变量和函数声明总是会被提升到当前作用域的顶部。
原因:
执行上下文的 创建阶段,创建VO对象的时候就已经检测过所有的 变量声明和函数声明了。
所以这个时候 它们已经存在了。
只不过 变量声明的值始终是undefined.而函数声明的值是一个函数在内存地址中的引用.

Javascript 执行上下文 context&scope的更多相关文章

  1. 深入理解javascript执行上下文(Execution Context)

    本文转自:http://blogread.cn/it/article/6178 在这篇文章中,将比较深入地阐述下执行上下文 - Javascript中最基础也是最重要的一个概念.相信读完这篇文章后,你 ...

  2. Javascript的“上下文”(context)

    一:JavaScript中的“上下文“指的是什么 百科中这样定义: 上下文是从英文context翻译过来,指的是一种环境. 在软件工程中,上下文是一种属性的有序序列,它们为驻留在环境内的对象定义环境. ...

  3. JavaScript执行上下文

    变量声明.函数声明为何会提升?js执行时是如何查找变量的?JavaScript中最基本的部分——执行上下文(execution context) 什么是执行上下文? 当JavaScript代码运行,执 ...

  4. javascript执行上下文学习一

    原文: http://web.jobbole.com/84044/ http://blog.csdn.net/github_34514750/article/details/52901781 1.三种 ...

  5. 深入理解JavaScript执行上下文、函数堆栈、提升的概念

    本文内容主要转载自以下两位作者的文章,如有侵权请联系我删除: https://feclub.cn/post/content/ec_ecs_hosting http://blog.csdn.net/hi ...

  6. 再看javascript执行上下文、变量对象

    突然看到一篇远在2010年的老文,作者以章节的形式向我们介绍了ECMA-262-3的部分内容,主要涉及到执行上下文.变量对象.作用域.this等语言细节.内容短小而精悍,文风直白而严谨,读完有酣畅淋漓 ...

  7. 图解Javascript——执行上下文

    什么是执行上下文? 执行上下文(Execution Context)是ECMAScript规范中用来描述 JavaScript 代码执行的抽象概念,规定了当前代码执行的环境(当前执行代码片段中的变量. ...

  8. javascript 执行上下文的理解

    首先,为什么某些函数以及变量在没有被声明以前就可以被使用,javascript引擎内部在执行代码以前到底做了些什么?这里,想信大家都会想到,变量声明提前这个概念: 但是,以下我要讲的是,声明提前的这个 ...

  9. javascript --执行上下文,作用域

    执行上下文 顾名思意就知道他是动态的,只在代码运行的时候产生 作用域 顾名思意就知道它是一个"领域",并且这个"领域"在一开始就规划好, 不会在改, var d ...

随机推荐

  1. linux日常管理-查看系统负载

    查看系统的负载常用命令w 16:32::15是系统时间 up 16 min 是开机使用时间 1 user 是登录的用户数 重要 load average:0.00 0.00 0.00 负载分别表示1分 ...

  2. /*用户登录注册页面输入框的设置*/<span>的使用

    <!DOCTYPE html> /*用户登录注册页面输入框的设置*/ <html lang="en"> <head> <meta char ...

  3. com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; che

    出现此种错误,我暂时遇到了两次. 1 我的字段的名称和数据库的关键字重合. 上图中的desc是默认降序排列的意思. 2 第二次出现的异常是我在重构代码阶段遇到的一个bug.不过我暂时不能理解,虽然解决 ...

  4. js页面跳转常用的几种方式(转)

    js页面跳转常用的几种方式 转载  2010-11-25   作者:    我要评论 js实现页面跳转的几种方式,需要的朋友可以参考下. 第一种: 复制代码代码如下: <script langu ...

  5. Flask09 原始输出、转义、XSS攻击、过滤器???

    1 怎么在jinja模板中原始输出模板语法 1.1 用双引号引起来后放到 {{ }} 中 例如 {{ "{{}}" }} 输出 1.2 利用raw 例如 {% raw %} {% ...

  6. Linux服务器监控工具--Nmon介绍

    一.Nmon介绍(详细请参考百度百科) 是一款分析 AIX 和 Linux 性能的免费工具,这个高效的工具可以工作于任何哑屏幕.telnet 会话.甚至拨号线路.另外,它并不会消耗大量的 CPU 周期 ...

  7. unreal3启动地图设置

    在defaultengine.ini中[URL]节: Map=MOBATinyMap.udkLocalMap=MOBATinyMap.udk 这里有Map和LocalMap两个属性,让人有点混淆,只好 ...

  8. 关于android上dpi/screen-size的厘清解释

    android定义了四种screen-size: small normal large xlarge 同时定义了六种dpi级别: ldpi (low) ~120dpimdpi (medium) ~16 ...

  9. 红米用adb连接显示unauthorized的解决办法

    网上能搜到的各种办法都试过了, 没一个可行: 1.大部份是用来解决usb不识别的,也就是adb devices不显示.但现在是有显示,只是unauthorized 2.我习惯用tcp连接,少根线,多台 ...

  10. ant安装和配置

    一.安装ant到官方主页http://ant.apache.org下载新版(我用的1.9.2)的ant,得到的是一个apache-ant-1.9.2-bin.zip的压缩包.将其解压到你的硬盘上,例如 ...