执行上下文(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. java继承示例

    package day07; class Fu { int num = 5; } class Zi extends Fu { int num =7; void show() { int num =9; ...

  2. Selenium并行启动多个浏览器

    如果你对 Selenium 自动化测试已经非常熟悉,你仅仅需要一个快速上手来使程序运行起来.本章节的内容能满足不同的技术层次,但是如果你仅仅需要一个可以快速上手的指引,那么就显得有点多.如果是这样,你 ...

  3. 字符串(String)

    字符串是由字符组成的数组,但在JavaScript中字符串是不可变的:可以访问字符串任意位置的文本,但是JavaScript并未提供修改已知字符串内容的方法. 常见功能: obj.length     ...

  4. 02_android下单元测试

    Java的单元测试JUnit. Java程序入口是main方法.一般不在安卓程序入口 @Override protected void onCreate(Bundle savedInstanceSta ...

  5. Java泛型通配符以及限定

    摘抄笔记 A:泛型的限定 /* * 将的酒店员工,厨师,服务员,经理,分别存储到3个集合中 * 定义方法,可以同时遍历3集合,遍历三个集合的同时,可以调用工作方法 */ import java.uti ...

  6. Freemarker01

    1 如何使用freemarker 1.1 导包 freemarker-2.3.19.jar 1.2 创建一个ftl文件作为模板 1.3 创建一个方法来将ftl模板和数据组合起来 2 利用maven实现 ...

  7. Entity Framework Code-First(9.6):DataAnnotations - StringLength Attribute

    DataAnnotations - StringLength Attribute: StringLength attribute can be applied to a string type pro ...

  8. svn的revert、checkout、clean up、setting

    svn revert 描述恢复所有对文件和目录的修改,并且解决所有的冲突状态. svn revert不会只是恢复工作拷贝中一个项目的内容,也包括了对属性修改的恢复.最终,你可以使用它来取消所有已经做过 ...

  9. Netty 线程模型与Reactor 模式

    前言 Netty 的线程模型是基于NIO的Selector 构建的,使用了异步驱动的Reactor 模式来构建的线程模型,可以很好的支持成百上千的 SocketChannel 连接.由于 READ/W ...

  10. FormsAuthentication.RedirectFromLoginPage 登录

    首先讲的这个东西是针对后台数据访问的比如我的后台是admin文件夹.那么我除非登陆成功才可以访问里面的东西.那么除了Session对象判断.和Cookies来判断还能用到FormsAuthentica ...