这是我在公众号 (高级前端进阶) 看到的文章, 现在做笔记
阅读笔记
JS 是单线程的语言, 执行顺序肯定是顺序执行, 但是 JS 引擎并不是一行一行地分析和执行程序, 而是一段一段地分析执行, 会先进行编译阶段然后才是执行阶段.
上代码
例子一: 变量提升
- // 下面是 foo 函数表达式, 变量 foo 已经创建了, 但是 函数表达式不会提升, 所以 foo()的时候, Uncaught TypeError: foo is not a function
- foo(); // Uncaught TypeError: foo is not a function
- var foo = function () {
- console.log('foo1');
- }
- foo(); // foo1,foo 重新赋值
- var foo = function () {
- console.log('foo2');
- }
- foo(); // foo2,foo 重新赋值
例子二: 函数提升
- foo(); // foo2
- function foo() {
- console.log('foo1');
- }
- foo(); // foo2
- function foo() {
- console.log('foo2');
- }
- foo(); // foo2
说明:(1), 函数声明可以被提升, 函数表达式不会提升;(2), 在同一作用域下, 多个同名函数声明, 后面的会替换前面的
例子三: 声明优先级, 函数> 变量
- foo(); // foo2
- var foo = function() {
- console.log('foo1');
- }
- foo(); // foo1,foo 重新赋值
- function foo() {
- console.log('foo2');
- }
- foo(); // foo1
函数声明优先级高于变量声明.
执行上下文
执行上下文总共有三种类型
全局执行上下文: 只有一个, 浏览器中的全局对象就是 Windows 对象, this 指向这个全局对象.
函数执行上下文: 存在无数个, 只有在函数被调用的时候才会被创建, 每次调用函数都会创建一个新的执行上下文.
Eval 函数执行上下文: 指的是运行在 eval 函数中的代码, 很少用而且不建议使用.
执行上下文栈
因为 JS 引擎创建了很多的执行上下文, 所以 JS 引擎创建了执行上下文栈 (Execution context stack,ECS) 来管理执行上下文.
当 JavaScript 初始化的时候会向执行上下文栈压入一个全局执行上下文, 我们用 globalContext 表示它, 并且只有当整个应用程序结束的时候, 执行栈才会被清空, 所以程序结束之前, 执行栈最底部永远有个 globalContext.
- ECStack = [ // 使用数组模拟栈
- globalContext
- ];
找不同
有如下两段代码, 执行的结果是一样的, 但是两段代码究竟有什么不同?
- var scope = "global scope";
- function checkscope(){
- var scope = "local scope";
- function f(){
- return scope;
- }
- return f();
- }
- checkscope();
- var scope = "global scope";
- function checkscope(){
- var scope = "local scope";
- function f(){
- return scope;
- }
- return f;
- }
- checkscope()();
答案是 执行上下文栈的变化不一样.
第一段代码:
- ECStack.push(<checkscope> functionContext);
- ECStack.push(<f> functionContext);
- ECStack.pop();
- ECStack.pop();
第二段代码:
- ECStack.push(<checkscope> functionContext);
- ECStack.pop();
- ECStack.push(<f> functionContext);
- ECStack.pop();
函数上下文:
[进阶 1-2 期] JavaScript 深入之执行上下文栈和变量对象(转)
来源: http://www.bubuko.com/infodetail-2863947.html