JavaScript(2)- Closures(闭包)and F
2018-04-22 本文已影响10人
sunboximeng
Closures
如果把函数代码作为返回值,就会把函数代码的外部环境一并保存起来(close in),以便该函数在被调用时使用。Closure is the fundation for Ajax.
function makeMultiplier (multiplier) {
console.log("111");
return (
function (x) {
console.log("222");
return multiplier*x;
}
);
}
makeMultiplier(2)
>>111
>>function (x) {
console.log("222");
return multiplier * x;
}
由于console.log("222")
没有输出,说明该匿名函数没有被执行,而是把他的代码作为返回值。因此参数 multiplier 并没有得到赋值。 但是由于闭包机制的存在,即便代码没有执行,变量没有赋值,代码里面用到的外部的变量也会得到保存。
var a = makeMultiplier(2)
>>111
a(3)
>>222
>>6
作用域和命名空间
作用域
Javascript的变量范围是以函数为基础的,并不是每一对大括号都能拥有它自己的作用范围。
function test() { // 一个作用域
for(var i = 0; i < 10; i++) { // 不是一个作用域
}
console.log(i); // 10
}
命名空间
当一个工程很大时,不用文件中的变量名、函数名和对象名,难免冲突。如果你在无意识的情况下重载了一个函数,Javascript根本不会提醒你。
HTML:
...
<head>
<script src="js/script111.js"></script>
<script src="js/script222.js"></script>
<script src="js/scriptApp.js"></script>
</head>
...
script111.js
function say() { return "My hobby is Popkart"; }
script222.js
function say() { return "My hobby is Reading books"; }
scriptApp.js
say();
输出My hobby is Reading books
,因为script222.js中的say()函数把script111.js中的say()函数覆盖了。因此需要把各自的代码都放在自己的命名空间里。虽然JavaScript并没有命名空间这一概念,但这种功能非常容易实现。
方法一:把代码封装在不重名的对象里。
script111.js
var fooSpace = {};
fooSpace.hobby = "Popkart";
foospace.say = function() {
return "My hobby is " + fooSpace.hobby;
}
script222.js
var barSpace = {};
barSpace.hobby = "Reading books";
barspace.say = function() {
return "My hobby is " + fooSpace.hobby;
}
scriptApp.js
fooSpace.say();
输出My hobby is Popkart
。这虽然减少了全局变量的个数,但是对象的属性(如 hobby)完全暴露在外面,外部很容易改变内部的状态。
方法二:Immediately-Invoked Function Expression
对象 + 函数 --> 选择性的暴露对象的属性
script111.js
(function (window) {
var fooSpace = {};
// 由于hobby变量在函数里面,也就不会和下面那个函数里的hobby变量冲突
// 因为函数拥有自己独立的作用域
var hobby = "Popkart";
// 只把say方法暴露出去
fooSpace.say = function () {
return "My hobby is " + hobby;
}
// 把fooSpace暴露在全局作用域
window.foo = fooSpace;
})(window);
script222.js
(function (window) {
var barSpace = {};
var hobby = "Reading books";
barSpace.say = function () {
return "My hobby is " + hobby;
}
window.bar = barSpace;
})(window);
scriptApp.js
foo.say();
bar.say();
bar.hobby // undefined。 hobby相当于是私有变量了,全局作用域无法访问它的值。