[JavaScript基础] 作用域,立即执行函数,闭包

作用域 scope

作用域链精解

[[scope]]:每个JavaScript函数都是一个对象,对象中有些属性我们可以访问,但有些不可以,这些属性仅提供JavaScript引擎存取,[[scope]]就是其中一个。

[[scope]]指的就是我们所说的作用域,其中存储了运行期上下文的集合。

作用域链:[[scope]]中所存储的执行期上下文对象的集合,这个集合呈链式链接,我们把这种链式链接叫做作用域链

运行期上下文:当函数执行时,会创建一个成为执行期上下文的内部对象。一个执行期上下文定义了一个函数执行时的环境,函数每次执行时对应的执行上下文都是独一无二的,所以多次调用一个函数会导致创建多个执行上下文,当函数执行完毕,它所产生的执行上下文被销毁。

function fn() {
  //代码逻辑
}
fn(); // 执行期上下文
fn(); // 执行期上下文,使用完销毁
……

查找变量:从作用域链的顶端依次向下查找。函数自身的作用域,在作用域链的顶端。

function a() {
  function b() {
    function c() {
    } 
    c();
  }
  b();
}
a();
/* 作用域链
a 定义 a.[[scope]] ==> 0 : GO
a 执行 a.[[scope]] ==> 0 : aAO
                       1 : GO
b 定义 b.[[scope]] ==> 0 : aAO
                       1 : GO
b 执行 b.[[scope]] ==> 0 : bAO
                       1 : aAO
                       2 : GO
c 定义 c.[[scope]] ==> 0 : bAO
                       1 : aAO
                       2 : GO
c 执行 c.[[scope]] ==> 0 : cAO
                       1 : bAO
                       2 : aAO
                       3 : GO
*/

立即执行函数

此类函数没有声明,在一次执行后即释放。适合做初始化工作,只执行一次的函数。

只有表达式才能被执行。

(function () {
  var a = 123;
  var b = 234;
  console.log(a + b); // 357
}())
//带参数
//上面括号是形参,下面括号是实参。
(function (a, b, c) {
  console.log(a + b + c)  // 6
}(1, 2, 3))
//带返回值
var num = (function (a, b, c) {
  var d = a + b + c;
  return d;
}(1, 2, 3))
console.log(num);
写法

(function([形参]){}([实参])) W3C官方建议这种写法
(function([形参]){})([实参])

//只有表达式才能被执行符号执行
function test() {
  console.log(123)
}()  //error
var test = function () {
  console.log(123)
}()  //123

在函数声明前面+ - !符号,可以把函数声明变成表达式,可让函数立即执行。但放弃了函数名字。

! function test() {
  console.log(123)
}() 
//
// 如果再执行test(),会报错。
// Uncaught ReferenceError: test is not defined

凡是表达式都能立即执行

function test(a, b, c, d) {
  console.log(a + b + c + d);
}(1, 2, 3, 4)
//不报错,但不执行。说的准确点是函数不自执行。
//浏览器会解析为test()函数和多个表达式(1, 2, 3, 4)
//两者没关系。

闭包

内部的函数保存到了外部,就是闭包。
闭包将造成原有作用域链不释放,造成内存泄漏。

// e.g 
function a() {
  function b() {
    var bbb = 234;
    console.log(aaa);
  }
  var aaa = 123;
  return b;
}
var glob = 100;
var demo = a();
demo();
// e.g
function a() {
  var num = 100;
  function b() {
    num ++;
    console.log(num)
  }
  return b;
}
var demo = a();
demo(); // 101
demo(); // 102

作用

实现共有变量
//累加
function add() {
  var count = 0;
  function num() {
    count++;
    console.log(count);  
  }
  return num;
}
var addNum = add();
addNum();  //1
………
可以做缓存(存储结构)
function demo() {
  var num = 100;
  function a() {
    num++;
    console.log(num);
  }
  function b() {
    num--;
    console.log(num);
  }
return [a, b]
}
var demoArr = demo();
demoArr[0](); // 101
demoArr[1](); // 100
可以实现封装,属性私有化
模块化开发,防止污染全局变量

你可能感兴趣的:([JavaScript基础] 作用域,立即执行函数,闭包)