如果这个问题过于宽泛,我会提前道歉。事实上,这是4个不同的问题,但都与相同的代码相关,我认为它们都围绕着相同的原则。
我今天决定使用JS多年后,实际上开始学习JS如何工作,而不是像在浏览器中运行的那样对待它。所以我开始深入研究jQuery代码,看看真正的JS开发人员如何使用langauge。就在那时我发现了一段看起来像下面代码的代码。请注意,我将此代码从此处的另一个堆叠帖子In Javascript, can you extend the DOM?中删除。所以这并不意味着编写此代码的人甚至不知道他在说什么。
var myDOM = (function(){ // #1
var myDOM = function(elems){ // #2
return new MyDOMConstruct(elems);
},
MyDOMConstruct = function(elems) {
this.collection = elems[1] ? Array.prototype.slice.call(elems) : [elems];
return this; // #3
};
myDOM.fn = MyDOMConstruct.prototype = {
forEach : function(fn) {
var elems = this.collection;
for (var i = 0, l = elems.length; i < l; i++) {
fn( elems[i], i );
}
return this;
},
addStyles : function(styles) {
var elems = this.collection;
for (var i = 0, l = elems.length; i < l; i++) {
for (var prop in styles) {
elems[i].style[prop] = styles[prop];
}
}
return this;
}
};
return myDOM; // #4
})();
1为什么使用var myDOM =(function(){})()声明函数;而不是var myDOM = function(){};
2为什么在myDOM函数中使用完全相同的名称声明另一个函数?为什么不将所有内部myDOM的逻辑放在外部myDOM函数中?
3为什么明确地返回“this”?这本来是自动完成的,对吗?
4这里发生了什么?它是否返回内部myDOM的构造函数?如果是这样,为什么?
更新
所以现在大部分都有意义。关于#1,我认为myDOM被分配了=之后定义的函数,但事实并非如此。它被分配给函数返回的任何东西。这恰好是一个功能。
我还不清楚#3。是的,我理解使用像这样的功能
console.log(MyDomConstruct('foo'))
会显示'undefined'。但这不是它的使用方式。这几行是
return new MyDomConstruct(elems);
如果语句像这样
,我可以理解明确返回“this”return MyDomConstruct(elems);
但事实并非如此。
答案 0 :(得分:9)
为什么使用var myDOM =(function(){})()声明函数;而不是var myDOM = function(){};
这就是所谓的self-invoking anonymous function
或self-executing anonymous function
。它就是这样,它在运行时调用它自己。你还会看到模式:
(function($){
}(jQuery));
在jQuery世界中非常多。同样的事情是,在运行时函数调用自身并保证$
符号在函数体中具有对jQuery
对象的引用。
在你的代码片段中,函数调用自身并返回myDOM
函数引用。
为什么要使用完全相同的名称在myDOM函数中声明另一个函数?为什么不将所有内部myDOM的逻辑放在外部myDOM函数中?
这只是一个惯例。它可以被称为任何你想要的,也许作者认为这样做很方便。这种模式的原因是隐私和安全。通过返回内部myDOM
引用,将创建closure
。所以后面声明了像
var mytest = myDOM([]);
您将无法访问MyDOMConstruct
,但您的内部功能确实可以访问。这样你就可以保护你的方法和变量。它也被称为method pattern
。在此上下文中始终是一个很好的阅读Douglas Crockford: Javascript the good parts
。
为什么要明确返回“this”?这本来是自动完成的,对吗?
不,函数默认会返回undefined
值。通过显式返回this
,您可以chain
方法(来自上面的示例调用):
mytest.forEach([]).addStyles([]); ...
因为每个方法都返回调用对象,在本例中为myDOM
。
这里发生了什么?它是否返回内部myDOM的构造函数?如果是这样,为什么?
我希望此时应该清楚。
修改强>
根据您的更新:
new MyDOMConstruct();
从{/ p>生成inherits
的新对象
MyDOMConstruct.prototype
如果没有new keyword
,this
将不会绑定到新对象。相反,它将绑定到全局对象(窗口),您将使用this
访问全局变量。
答案 1 :(得分:6)
<强> 1。为什么使用var myDOM = (function() {})();
而不是var myDOM = function() {};
使用的表单是自执行功能。这意味着myDOM设置为函数返回的任何值。第二种形式将myDOM设置为函数,但不立即执行该函数。
var myDOM = (function() { // <== This is a function that does something
// Something
})(); // The function is executed right HERE with ().
<强> 2。为什么要使用完全相同的名称在myDOM函数中声明另一个函数?为什么不将所有内部myDOM的逻辑放在外部myDOM函数中?
因为你在最后返回内部myDOM函数....所以命名实际上是有意义的,尽管它最初是令人困惑的。这通常用于在JS中创建私有变量。由于内部函数可以访问作用域(自执行匿名函数),但用户不会。
var myDOM = (function() { // <== This is a function that is going to return
// a function / object
var myDOM = function() { // <== We're going to return this
... // The outer myDom will be set to it
}; // So it's actually helpful to name
// it the same for clarity.
return myDOM;
})();
// Now we can access that inner object by using the outer myDOM.
// We could access the inner object using myDOM even if the inner object
// was named otherTHING... It's confusing to acces something
// called otherTHING in the code by
// writing myDOM().... so better name the inner returned function
// myDOM as well.
因此内部对象可以被命名为任何内容,并且可以使用myDOM()
执行,但是如果您命名内部函数blah
,您仍然可以使用myDOM()
执行它。 ..那不是很清楚......更好地命名它。
第3。为什么明确地返回“这个”?这本来是自动完成的,对吗?
不,如果您不写任何内容,Javascript会自动返回undefined
。 MDC reference: 。
返回this
通常用于保留方法的上下文。它曾经使方法($(here).is().a().chain().of().methods()
)的链接成为可能。因此链中的方法知道它正在运行的上下文。
答案 2 :(得分:3)
对自动执行的匿名函数再说一句。在(function() { })();
块中包装一些JavaScript是一种创建私有命名空间的方法。除了返回的值(在本例中为myDOM
)之外,您在内部函数中执行的所有操作都将是私有函数。
那就是你可以拯救地做像
这样的事情var counter = (function() {
var i = 0;
var counter = function() {
alert(i++);
return i;
}
return counter;
})();
counter(); // will alert 0
counter(); // will alert 1
// ... and so on
从函数外部保留一些内部状态机密。第二个原因,如其他帖子中所述,它不会使用变量i
污染全局命名空间。这就是为什么最好在jQuery插件开发中使用这些函数的原因。
答案 3 :(得分:1)
与此相同:
(function () {
function b(a) {
return new c(a)
}
function c(a) {
this.a = a[1] ? Array.prototype.slice.call(a) : [a];
return this
}
b.b = c.prototype = {};
return b
})();
希望有帮助......:)
答案 4 :(得分:1)
例如: var fn =(function(){ return function(){alert(11)}; })(); 当代码运行时,现在fn = function(){alert(11)}; 试试吧!!!