[JS]09.作用域&闭包例子

250 阅读2分钟

1. 变量提升

/*
  EC(G) 创建全局作用域
  变量提升:
    var a; 
    var b;
    var c; 
    test = 0x000;  作用域链[[scope]]:EC(G)
  执行代码
*/
var a = 10,
    b = 11,
    c = 12;
function test(a) {
  /*
    EC(TEST) 函数作用域
      作用域链<EC(TEST), EC(G)>
      形参赋值:a = 10;当前上下文 a 私有
      变量提升: var b; b私有的
  */
  a = 1;
  var b = 2;
  c = 3;   // c不是EC(TEST)私有的,向上级上下文EC(G)找
}
test(10); // 进test执行
console.log(a, b, c);  // 10 11 3

2. 函数的arguments参数

  • arguments的特点
    • 在JS非严格模式下,当初始化arguments形参赋值完成后,会给两者建立一个映射机制,集合中的每一项和对应的形参变量绑定在一起,一个修改都会跟着修改,而且只会发生在代码执行之前建立这个机制
    • 在JS严格模式下,没有映射机制,也没有arguments.callee这个属性,箭头函数中没有arguments
/*
  全局上下文EC(G)
  变量提升
    - var a;
    - b = 0x000; [[scope]]: EC(G);
    
*/
var a = 4;
function b(x, y, a) {
  /*
     私有上下文EC(b)
     初始化作用域链<EC(b), EC(G)>
     初始化函数的this:window
     初始化 arguments(实参集合,类数组):
       {
         0: 1, 1: 2, 2: 3, 
         length: 3, 
         callee: function b(){...}
       }
     形参赋值:x = 1  y = 2 a = 3 私有变量
     变量提升:无
  */
  console.log(a);  // 3
  arguments[2] = 10;  // a=10
  console.log(a);  // 10
}
a = b(1, 2, 3);  // 函数执行无返回值 undefined
console.log(a);  // undefined
function fn(x, y, z) {
  /*
    arguments: {0: 10, 1: 20}
  */
  x = 100;
  console.log(arguments[0]);  // 100
  
  arguments[1] = 200;
  console.log(y);   // 200
  
  z = 300;
  console.log(arguments[2])  // undefined
}
function fn() {
  // 存储的是当前函数本省,这样操作时为了方便递归调用
  console.log(argument.callee)
}
fn();

3.匿名函数具名化

  • 匿名函数具名化,只能在匿名函数中用这个名字 image.png
Array.prototype.unique = function unique() {};
console.log(unique)  // Uncaught ReferenceError: unique is not defined
var b = 10;
(function b() {
  // 匿名函数具名化之后,此时上下文中的b都是匿名函数本身(不允许修改)
  b = 20;
  console.log(b) // function b() {...}
})();
console.log(b)  // 10

image.png

4.

/*
  全局作用域EC(G)
  变量提升
    - var test;
*/
var test = (function (i) {
  /*
    自执行函数执行EC(any)
    作用域链: <EC(any), EC(G)>
    形参赋值: i= 2
    变量提升:无
  */
  return function() {
    /*
       test(5)执行 作用域 EC(test)
       作用域链: <EC(test), EC(G)>
    */
    alert(i *= 2)
  } // return 0x001; [[scope]]:EC(any)
})(2);

test = 0x001;

test(5); // i = i*2  4

5.套娃

function fun(n, o) {
  console.log(o);
  return {
    fun: function(m) {
      return fun(m, n)
    }
  }
}
var c = fun(0).fun(1);
c.fun(2);
c.fun(3);
  • 变量提升之后代码执行

image.png