深入 JavaScript(6) - 一静一动

这里是JavaScript核心的内容了. 挺多的JavaScript测试题也是围绕这个出的.
这里的一静一动指的是:
  • 静, 词法作用域 - Lexical scoping
  • 动, 动态绑定this的值
一、静
在JavaScript中函数有静态的词法作用域. 这是什么意思?
当我们写好了代码, 如 lexical.js , 那么此刻, 代码里的各个函数的作用域就已经确定了. 与这个函数是否被调用, 在哪儿调用, 被谁调用无关.
作用域大都被说成作用域链, 它是有层级关系的, 从顶层向底层直到全局作用域; 或者说从链头部向尾部延伸, 直到最后面的全局空间Global.
Global总在最后.
此作用域是函数的一个内部属性, 代码访问不到. 技术书籍中通常用 [[scope]] 这个名字来表示这个静态的词法作用域.
 
静 和 作用域 都说了, 那么这个词法是什么?
JavaScript解释器只需要分析源代码的文本就能确定[[scope]]. 嗯..我是这么理解的
 
例:
(1)
var scope = "global";

function foo() {

  console.log(scope);

}

function bar() {

  var scope = "local";

  foo();

  console.log(scope);

}



bar();

// global

// local

(2)
 
var scope = "global",

  ns = {

    scope: "In object",

    bar: function() {

      console.log(scope); // !this.scope

    }

  };



ns.bar();

//result global

 (3)

var scope = "global",

  bar = function() {

    var scope = "In bar";



    return function() {

      // var scope = "In anony fn";

      console.log(scope);

    };

  };



bar()();

 

======
稍微讲下, 这里形成了闭包, 比上面的例子稍复杂些, 但是判断词法作用域却非常简单! 为什么, 因为我们不用去考虑什么闭包什么调用逻辑,
我们只要分析代码文本就行了!
例子里一共出现2个函数, 3个scope变量(算上我注释掉的). 前提我们知道JavaScript中函数能产生新的作用域.
那么, 我们看一下return的这个匿名函数的词法作用域 [[scope]] 是什么?
分析代码文本, 首先有匿名函数自己, 往下是包着它的 bar 函数, 再往下发现没有函数了, 那就到Global了.
[[scope]] = Returned anonymous function -> bar function -> global
当我们确定了[[scope]], 当解析标识符scope的时候就是从这个链的顶端 anonymous function 向底部 Global 查找;
 
那么就上面的例子, bar()()调用时, 我们相当于在Global空间里调用了bar函数返回的匿名函数, 此函数打印 console.log(scope). 虽说是在Global里打印scope, 但是结果
是"In bar". 因为无论在哪调用, [[scope]]早已经确定! [[scope]] = Returned anonymous function -> bar function -> global
当打印scope的时候, 从Returned anonymous function开找, 发现没有 scope(被我注释掉了), 找下一个, bar function 发现目标, 打印之.
 
 

你可能感兴趣的:(JavaScript)