-
Notifications
You must be signed in to change notification settings - Fork 13
作用域闭包 #30
Copy link
Copy link
Open
Description
-
看起来像闭包。
function foo(){ var a = 2; function bar(){ console.log(a); } bar(); } foo();
-
这才是闭包。
function foo(){ var a = 2; function bar(){ console.log(a); } return bar; } var baz = foo(); baz();
-
把内部函数 baz 传递给 bar, 当调用这个内部函数时(现在叫做 fn),它涵盖的 foo()
内部作用域的闭包就可以观察到了。因此它能够访问 a。function foo() { var a = 2; function baz(){ console.log(a); } bar(baz); } function bar(fn) { fn(); }
-
把 baz 分配给全局变量
var fn; function foo(){ var a = 2; function baz(){ console.log(a); } fn = baz; } function bar(){ fn(); } foo(); bar();
-
无论通过何种手段将内部函数传递到所在的词法作用域以外,
它都会持有对原始定义作用有的引用,
无论在何处执行这个函数都会使用闭包。function wait(message) { setTimeout(function timer(){ console.log(message); },1000) } wait("Hello,Closure!")
/*
jquery
*/function setupBot(name,selector){ $(selector).click(function activator(){ console.log("Activating: " + name); }); } setupBot("console BOT1","#bot_1"); setupBot("console BOT2","#bot_2");
-
IIFE
var a = 2; (function IIFE(){ console.log(a); })();
-
循环和闭包
for(var i = 1; i <= 5; i++) { setTimeout(function timer(){ console.log(i) },i*1000) } for(var i = 0; i<=5; i++) { (function(j){ setInterval(function(){ console.log(j); },1000); })(i); }
// 每隔一秒钟打印1,2,3,4,5 function foo(arr){ var i = 0; return function(){ setInterval(function(){ console.log(arr[i++]); },1000); }() }
(function(arr){ var i=0,length=arr.length; (function a(){ setTimeout(function(){ console.log(arr[i++]); i<length&&a(); },1000) }()) }([1,2,3,4]))
-
模块
function coolModule() {
var sth = "cool";
var another = [1,2,3];
function doSth() {
console.log(sth);
}
function doAnother() {
console.log(another.join("!"));
}
return {
doSth: doSth,
doAnother : doAnother
}
}
var foo = new coolModule();
foo.doSth();
foo.doAnother();- 模块模式需要两个必要条件:
- 必须有外部的封闭函数,该函数必须至少
被调用一次(每次调用都会创建一个新的模块实例) - 封闭函数必须至少返回至少一个内部函数,
这样内部函数才能在私有作用域中形成闭包,
并且可以访问或者修改私有的状态。
- 必须有外部的封闭函数,该函数必须至少
- 模块模式另一个简单强大的变化用法是,命名将要作为公共API 返回的对象。
``` js
var foo = (function coolModule(id){
function change(){
publicAPI.identify = identify2;
}
function identify1(){
console.log(id);
}
function identify2(){
console.log(id.toUpperCase());
}
var publicAPI = {
change:change,
identify: identify1
};
return publicAPI;
})("foo module");
foo.identify();
foo.change();
foo.identify();
```
- 现代的模块管理
``` js
var MyModules = (function Manger() {
var modules = {};
function define(name, deps, impl) {
for (var i = 0; i < deps.length; i++) {
deps[i] = modules[deps[i]];
}
modules[name] = impl.apply(impl, deps);
}
function get(name) {
return modules[name];
}
return {
define: define,
get: get
}
})();
MyModules.define("bar", [], function() {
function hello(who) {
return "Let me introduce: " + who;
}
return {
hello: hello
};
});
MyModules.define("foo", ["bar"], function(bar) {
var hungry = "hippo";
function awesome() {
console.log(bar.hello(hungry).toUpperCase());
}
return {
awesome: awesome
};
});
var bar = MyModules.get("bar");
var foo = MyModules.get("foo");
console.log(bar.hello("hippo"));
foo.awesome();
```
当函数可以记住并访问所在的词法作用域,即使函数时在当前词法作用域之外执行,这时就产生了闭包。
模块有两个主要特征:
- 为创建内部作用域而调用了一个包装函数;
- 包装函数的返回值必须至少包含一个队内部函数的引用,这样就会创建涵盖整个包装函数内部作用域的闭包。
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels