function getName() { var name = "美女的名字"; console.log(name);//"美女的名字"}function displayName() { console.log(name); //报错}但是为了得到美女的名字,不死心的单身汪把代码改成了这样:function getName() { var name = "美女的名字"; function displayName() { console.log(name);} return displayName;}var 美女 = getName(); 美女() //"美女的名字"这下,美女是一个闭包了,单身汪想怎么玩就怎么玩了。(但并不推荐单身汪用中文做变量名的写法,大家不要学)。function getOuter(){ var date = "815"; function getDate(str){ console.log(str + date); //访问外部的date } return getDate("今天是:"); //"今天是:815"}getOuter();getDate是一个闭包,该函数执行时,会形成一个作用域A,A中并没有定义变量date,但它能在父一级作用域中找到该变量的定义。function getOuter(){ var date = "815"; function getDate(str){ console.log(str + date); //访问外部的date } return getDate;//外部函数返回}var today = getOuter();today("今天是:"); //"今天是:815"today("明天不是:"); //"明天不是:815"3、闭包可以更新外部变量的值function updateCount(){ var count = 0; function getCount(val){ count = val; console.log(count); } return getCount;//外部函数返回}var count = updateCount();count(815); //815count(816); //816作用域链// my_script.js"use strict";var foo = 1;var bar = 2;在全局环境中,创建了两个简单地变量。如前面所说,此时变量对象是全局对象。
"use strict";var foo = 1;var bar = 2;function myFunc() { //-- define local-to-function variables var a = 1; var b = 2; var foo = 3; console.log("inside myFunc");}console.log("outside");//-- and then, call it:myFunc();当myFunc被定义的时候,myFunc的标识符(identifier)就被加到了当前的作用域对象中(在这里就是全局对象),并且这个标识符所引用的是一个函数对象(function object)。函数对象中所包含的是函数的源代码以及其他的属性。其中一个我们所关心的属性就是内部属性[[scope]]。[[scope]]所指向的就是当前的作用域对象。也就是指的就是函数的标识符被创建的时候,我们所能够直接访问的那个作用域对象(在这里就是全局对象)。"use strict";function createCounter(initial) { var counter = initial; function increment(value) { counter += value; } function get() { return counter; } return { increment: increment, get: get };}var myCounter = createCounter(100);console.log(myCounter.get()); // 返回 100myCounter.increment(5);console.log(myCounter.get()); // 返回 105当调用createCounter(100)时,内嵌函数increment和get都有指向createCounter(100) scope的引用。如果createCounter(100)没有任何返回值,那么createCounter(100) scope不再被引用,于是就可以被垃圾回收。但是因为createCounter(100)实际上是有返回值的,并且返回值被存储在了myCounter中,所以对象之间的引用关系发生变化。//myScript.js"use strict";function createCounter(initial) { /* ... see the code from previous example ... */}//-- create counter objectsvar myCounter1 = createCounter(100);var myCounter2 = createCounter(200);myCounter1 和 myCounter2创建之后,关系图是酱紫的:
在上面的例子中,myCounter1.increment和myCounter2.increment的函数对象拥有着一样的代码以及一样的属性值(name,length等等),但是它们的[[scope]]指向的是不一样的作用域对象。
这才有了下面的结果:
var a, b;a = myCounter1.get(); // a 等于 100b = myCounter2.get(); // b 等于 200myCounter1.increment(1);myCounter1.increment(2);myCounter2.increment(5);a = myCounter1.get(); // a 等于 103b = myCounter2.get(); // b 等于 205作用域和this