A functional argument (“Funarg”) — is an argument which value is a function.
函数式参数(“Funarg”) —— 是指值为函数的参数。
function exampleFunc(funArg) {
funArg();
}
exampleFunc(function () {
alert('funArg');
});
(function functionValued() {
return function () {
alert('returned function is called');
};
})()();
(function selfApplicative(funArg) {
if (funArg && funArg === selfApplicative) {
alert('self-applicative');
return;
}
selfApplicative(selfApplicative);
})();
(function selfReplicative() {
return selfReplicative;
})();
// 接受集合的函数
function registerModes(modes) {
modes.forEach(registerMode, modes);
}
// 用法
registerModes(['roster', 'accounts', 'groups']);
// 自复制函数的声明
function modes(mode) {
registerMode(mode); // 注册一个mode
return modes; // 返回函数自身
}
// 用法,modes链式调用
modes('roster')('accounts')('groups')
//有点类似:jQueryObject.addClass("a").toggle().removClass("b")
function testFn(funArg) {
// funarg激活时, 局部变量localVar可以访问了
funArg(10); // 20
funArg(20); // 30
}
testFn(function (arg) {
var localVar = 10;
alert(arg + localVar);
});
function testFn() {
var localVar = 10;
function innerFn(innerParam) {
alert(innerParam + localVar);
}
return innerFn;
}
var someFn = testFn();
someFn(20); // 30
var z = 10;
function foo() {
alert(z);
}
foo(); // 10 – 使用静态和动态作用域的时候
(function () {
var z = 20;
foo(); // 10 – 使用静态作用域, 20 – 使用动态作用域
})();
// 将foo作为参数的时候是一样的
(function (funArg) {
var z = 30;
funArg(); // 10 – 静态作用域, 30 – 动态作用域
})(foo);
闭包是代码块和创建该代码块的上下文中数据的结合。
var x = 20;
function foo() {
alert(x); // 自由变量"x" == 20
}
// 为foo闭包
fooClosure = {
call: foo // 引用到function
lexicalEnvironment: {x: 20} // 搜索上下文的上下文
};
var x = 10;
function foo() {
alert(x);
}
(function (funArg) {
var x = 20;
// 变量"x"在(lexical)上下文中静态保存的,在该函数创建的时候就保存了
funArg(); // 10, 而不是20
})(foo);
var x = 10;
function foo() {
alert(x);
}
// foo是闭包
foo: <FunctionObject> = {
[[Call]]: <code block of foo>,
[[Scope]]: [
global: {
x: 10
}
],
... // 其它属性
};
var global = this;
var x = 10;
var foo = (function () {
var y = 20;
return function () {
alert(y);
};
})();
foo(); // 20
alert(foo.__parent__.y); // 20
foo.__parent__.y = 30;
foo(); // 30
// 可以通过作用域链移动到顶部
alert(foo.__parent__.__parent__ === global); // true
alert(foo.__parent__.__parent__.x); // 10
var firstClosure;
var secondClosure;
function foo() {
var x = 1;
firstClosure = function () { return ++x; };
secondClosure = function () { return --x; };
x = 2; // 影响 AO["x"], 在2个闭包公有的[[Scope]]中
alert(firstClosure()); // 3, 通过第一个闭包的[[Scope]]
}
foo();
alert(firstClosure()); // 4
alert(secondClosure()); // 3
var data = [];
for (var k = 0; k < 3; k++) {
data[k] = function () {
alert(k);
};
}
data[0](); // 3, 而不是0
data[1](); // 3, 而不是1
data[2](); // 3, 而不是2
activeContext.Scope = [
... // 其它变量对象
{data: [...], k: 3} // 活动对象
];
data[0].[[Scope]] === Scope;
data[1].[[Scope]] === Scope;
data[2].[[Scope]] === Scope;
var data = [];
for (var k = 0; k < 3; k++) {
data[k] = (function _helper(x) {
return function () {
alert(x);
};
})(k); // 传入"k"值
}
// 现在结果是正确的了
data[0](); // 0
data[1](); // 1
data[2](); // 2
data[0].[[Scope]] === [
... // 其它变量对象
父级上下文中的活动对象AO: {data: [...], k: 3},
_helper上下文中的活动对象AO: {x: 0}
];
data[1].[[Scope]] === [
... // 其它变量对象
父级上下文中的活动对象AO: {data: [...], k: 3},
_helper上下文中的活动对象AO: {x: 1}
];
data[2].[[Scope]] === [
... // 其它变量对象
父级上下文中的活动对象AO: {data: [...], k: 3},
_helper上下文中的活动对象AO: {x: 2}
];
var data = [];
for (var k = 0; k < 3; k++) {
(data[k] = function () {
alert(arguments.callee.x);
}).x = k; // 将k作为函数的一个属性
}
// 结果也是对的
data[0](); // 0
data[1](); // 1
data[2](); // 2
function getElement() {
[1, 2, 3].forEach(function (element) {
if (element % 2 == 0) {
// 返回给函数"forEach"函数
// 而不是返回给getElement函数
alert('found: ' + element); // found: 2
return element;
}
});
return null;
}
var $break = {};
function getElement() {
try {
[1, 2, 3].forEach(function (element) {
if (element % 2 == 0) {
// // 从getElement中"返回"
alert('found: ' + element); // found: 2
$break.data = element;
throw $break;
}
});
} catch (e) {
if (e == $break) {
return $break.data;
}
}
return null;
}
alert(getElement()); // 2
再说一下,因为作用域链,使得所有的函数都是闭包(与函数类型无关: 匿名函数,FE,NFE,FD都是闭包)。
[1, 2, 3].sort(function (a, b) {
... // 排序条件
});
[1, 2, 3].map(function (element) {
return element * 2;
}); // [2, 4, 6]
someCollection.find(function (element) {
return element.someProperty == 'searchCondition';
});
[1, 2, 3].forEach(function (element) {
if (element % 2 != 0) {
alert(element);
}
}); // 1, 3
(function () {
alert([].join.call(arguments, ';')); // 1;2;3
}).apply(this, [1, 2, 3]);
var a = 10;
setTimeout(function () {
alert(a); // 10, after one second
}, 1000);
//...
var x = 10;
// only for example
xmlHttpRequestObject.onreadystatechange = function () {
// 当数据就绪的时候,才会调用;
// 这里,不论是在哪个上下文中创建
// 此时变量“x”的值已经存在了
alert(x); // 10
};
//...
var foo = {};
// 初始化
(function (object) {
var x = 10;
object.getX = function _getX() {
return x;
};
})(foo);
alert(foo.getX()); // 获得闭包 "x" – 10