乐趣区

关于前端:前端JavaScript作用域和运行分析

作用域

JavaScript 中的作用域分为 全局作用域 函数作用域 块作用域

全局作用域

对于全局范畴内申明的变量,能够在任何中央拜访。

var messge = 'Hello'
function say(){console.log(message)
}
say(); // Hello

函数作用域

在函数内申明的变量,只能从该函数外部拜访。

function say() {
  var messge = 'Hello';
  console.log(messge);
}
say(); // Hello
console.log(greeting); // ReferenceError: messge is not defined

块作用域

ES6 引入了 letconst 关键字,它们申明的变量只能从该代码块内拜访。

{
  let messge = 'Hello';
  console.log(messge);
}
console.log(messge); // ReferenceError: messge is not defined

动态作用域

在词法剖析时(编译时)确定。

let number = 42;
function printNumber() {console.log(number);
}
function log() {
  let number = 54;
  printNumber();}

log(); // 42

作用域链

JavaScript 运行时,引擎首先会在以后范畴内查找变量,如果找不到,会向父作用域查一层一层向上查找,始终找到顶层全局作用域,如果还是找不到就返回undefined

var g = 'Global hello'
function f1() {
    var g1 = 'G1 hello';
    function f2() {
        var g2 = 'G2 hello'
        function f3() {console.log(g, g1, g2)
        }
          f3()}
      f2();}
f1(); // Global hello G1 hello G2 hello

运行剖析

执行上下文

执行上下文 是执行一段 JavaScript 的环境,它存储了执行代码的一些必要信息。执行上下文分 全局执行上下文 函数执行上下文

  • 全局执行上下文 ,一个程序中只会有一个,函数之外的代码都在 全局执行上下文 中运行。
  • 函数执行上下文 ,函数在每次调用时都会创立一个对应的 函数执行上下文

执行上下文的蕴含 变量环境 Variable environment), 作用域链Scope chain),this 指向。

  • 变量环境,函数外部所有的变量和对象援用和调用参数。
  • 作用域链,以后函数之外的变量的援用组成。
  • this 指向。

从 JavaScript 运行时的内存构造来看,调用栈就是存储 执行上下文 的汇合。

案例

案例一

这是一个一般的 JavaScript 例子,运行流程剖析:

var msg = 'Global hello'

function say() {
    var msg = 'Hello'
      return msg;
}

var s = say();
console.log(message) // Hello
  1. 创立 全局执行上下文,而后入调用栈。
  2. 调用函数 say(),创立say()函数执行上下文,并入调用栈。
  3. 执行完 say() 函数将后果返回,更新全局执行上下文里的s 变量。
  4. say 函数的执行上下文弹出栈。

案例二

这个例子跟下面不同的是返回值是函数,这个匿名函数也称闭包,它拜访了函数内部的变量,即便内部 函数执行上下文 被弹出栈后,它仍然能够持有内部变量的援用。运行剖析如下:

var msg = 'Global hello'

function say() {
    var msg = 'Hello'
    return function() {console.log(msg)
    };
}

var s = say();
s()
  1. 创立 全局执行上下文,而后入调用栈。
  2. 调用函数 say(),创立say()函数执行上下文,并入调用栈。
  3. 执行完 say() 函数将后果返回,更新全局执行上下文里的s 变量,s 是函数类型,它仍然持有say var = msg 援用。
  4. say 函数的执行上下文弹出栈。
  5. 执行 s(),创立 s()函数执行上下文
  6. s() 函数的执行上下文弹出栈。

思考题

在脑海里动静执行上面代码。

题目一:

var msg = 'Global hello'

function getMsgFunc() {
    var msg = 'Hello';
    function getMsg() {return msg;}
    return getMsg();}
console.log(getMsgFunc());

题目二:

var msg = 'Global hello'

function getMsgFunc() {
    var msg = 'Hello';
    function getMsg() {return msg;}
    return getMsg;
}
console.log(getMsgFunc()());

题目三:

     var msg = 'Global hello'

  var obj = {
    msg : 'Hello',

    getMsgFunc : function(){return function(){return this.msg;};
    }
  };
  console.log(obj.getMsgFunc()());

题目四:

     var msg = 'Global hello'

  var obj = {
    msg : 'Hello',

    getMsgFunc : function(){
              var that = this
      return function(){return that.msg;};
    }
  };
  console.log(obj.getMsgFunc()());
退出移动版