JavaScript 闭包(Closure)

134 阅读1分钟

概述

闭包就是函数在被创建的时候,由自身及其所在的语法环境组合成的集合。

行为

1. 内部函数可访问外部变量;

内部函数正常访问外部变量。

function outer () {
  var name = 'outer';
  function inner () {
    console.log(name);
  }
  inner();
}
outer(); // outer

2. 即使外部函数已经执行完毕,内部函数仍然能访问外部变量;

function outer () {
  var name = 'outer';
  function inner () {
    console.log(name);
  }
  return inner;
}
var caller = outer();
caller(); // outer

3. 每个闭包都有自己的语法环境;

function outer (outerInput) {
  function inner (innerInput) {
    console.log('innerInput: ' + innerInput + ', outerInput: ' + outerInput);
    return inner
  }
  return inner;
}
var caller = outer(1);
caller(2); // innerInput: 2, outerInput: 1
caller(3); // innerInput: 3, outerInput: 1
function outer (outerInput) {
  function inner (innerInput) {
    console.log('innerInput: ' + innerInput + ', outerInput: ' + outerInput);
    return inner
  }
  return inner;
}
var caller1 = outer(1);
var caller2 = outer(2);
caller1(2); // innerInput: 2, outerInput: 1
caller2(3); // innerInput: 3, outerInput: 2

应用

1. 外部函数可以调用内部变量;

function init () {
  var baseNumber = 3;
  var otherBaseNumber = 5;
  function getRelation (compareNumber) {
    return baseNumber < compareNumber ? 'less than' : compareNumber === baseNumber ? 'equal with' : 'greater than';
  }
  function compareWith (compareNumber) {
    var relation = getRelation(compareNumber);
    return 'baseNumber: ' + baseNumber + ', compareNumber: ' + compareNumber + ', baseNumber is ' + relation +' compareNumber.';
  }
  function setBaseNumber (newNumber) {
    baseNumber = newNumber;
  }
  function getBaseNumber () {
    return baseNumber;
  }
  function baseAndOtherBaseNumber () {
    return 'baseNumber: ' + baseNumber + ', otherBaseNumber: ' + otherBaseNumber + ', ' + baseNumber + ' - ' + otherBaseNumber + ' = ' + (baseNumber - otherBaseNumber) + '';
  }
  return {
    compareWith: compareWith,
    setBaseNumber: setBaseNumber,
    getBaseNumber: getBaseNumber,
    baseAndOtherBaseNumber: baseAndOtherBaseNumber
  };
}

var caller = init();
console.log(caller.getBaseNumber()) // 3
console.log(caller.baseAndOtherBaseNumber()) // baseNumber: 3, otherBaseNumber: 5, 3 - 5 = -2
console.log(caller.compareWith(1)) // baseNumber: 3, compareNumber: 1, baseNumber is greater than compareNumber. 
caller.setBaseNumber(10)
console.log(caller.getBaseNumber()) // 10
console.log(caller.baseAndOtherBaseNumber()) // baseNumber: 10, otherBaseNumber: 5, 10 - 5 = 5
console.log(caller.compareWith(1)) // baseNumber: 10, compareNumber: 1, baseNumber is greater than compareNumber.

注意项

1. 闭包使得局部变量常驻内存,会导致内存泄漏;

以上是个人对变量提升的理解,如有错误处,希望大家多多包涵并指正。