我在这里很困惑。有人可以帮我从这里的函数定义中剥离层吗?最外面的括号是干什么用的?为什么参数(p)可以在}之后,它用于哪个函数?哪里需要q?为什么p以后可以直接调用publish()?
var p = {};
(function(q) {
q.publish = function(topic, data){
...
};
}(p));
...
p.publish("inbox", "hello");
我在这里很困惑。有人可以帮我从这里的函数定义中剥离层吗?最外面的括号是干什么用的?为什么参数(p)可以在}之后,它用于哪个函数?哪里需要q?为什么p以后可以直接调用publish()?
var p = {};
(function(q) {
q.publish = function(topic, data){
...
};
}(p));
...
p.publish("inbox", "hello");
它只是创建函数并立即执行它。
例如:
var foo = function() {
return 5;
}();
console.log(foo);
将打印5
。
如果您想了解更多信息,请阅读这篇优秀的文章http://benalman.com/news/2010/11/immediately-invoked-function-expression/
我想从我共享的链接中引用模块模式示例。
var counter = (function(){
var i = 0;
return {
get: function(){
return i;
},
set: function( val ){
i = val;
},
increment: function() {
return ++i;
}
};
}());
console.log(counter.get());
counter.set(3);
console.log(counter.increment());
console.log(counter.i);
输出
0
4
undefined
i
在这里,我们在将其设为私有的同时动态地创建了一个对象。这称为闭包属性。
将函数放在括号中意味着 JS 解释器将其作为函数表达式,因此它可以是匿名的(即没有声明的名称)。最后添加()
意味着立即调用该函数。所以,例如:
(function() {
alert('Hi');
}());
...声明一个没有参数的非常简单的函数,并立即调用它。一个稍微复杂的带参数的可能看起来像这样:
(function(someArgument) {
alert(someArgument);
}('Hi'));
这会提醒“嗨”,因为该字符串'Hi'
在调用时会传递给匿名函数。
因此,以此为背景,以下是您的代码逐行执行的操作:
var p = {}; // declare variable p, referencing an empty object
(function(q) { // make an anonymous function expression that takes one argument, q
q.publish = function(topic, data){ // add a property 'publish' to whatever q is,
... // where 'publish' is a function that takes
}; // two arguments
}(p)); // call the anonymous function, passing p in
...
p.publish("inbox", "hello"); // call the method 'publish' that was added to p
q
您询问的参数从 中获取值,p
因此它引用同一个空对象,但随后将.publish()
方法添加到该对象。
这个一般概念称为“立即调用函数表达式”或 IIFE。
通常,如果 IIFE 只是像那样单独坐在那里(即,没有分配另一个变量等于它),那么它可以在不将它们添加到全局范围的情况下临时创建工作变量/函数,因为在 JavaScript 中,范围选项基本上是全局或函数。您显示的代码没有这样做,但这是一个简单的示例:
(function() {
var x = 0;
for (var i = 0; i < 100; i++)
x += i;
alert (x);
}());
// here x and i are not accessible because they're local to the function above.
这是一个自我执行的功能。在这里使用q
是没用的,因为q === p
.
var p = 'hello';
function f(q){ return q; }; f(p); // "hello"
(function(q){ return q; }(p)); // "hello"
(function(){ return p; }()); // "hello"
/*(*/function(){ return p; }()/*)*/; // SyntaxError: Unexpected token (
此模式通常用于为变量创建私有上下文。这是一个众所周知的例子:
var counter = function(){
var i = 0;
return function(){
return ++i;
};
}();
counter(); // 1
counter(); // 2
i; // undefined
看看这篇很棒的文章: http: //www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html。