如果这个问题太宽泛,我会提前道歉.事实上,这是4个不同的问题,但都与相同的代码相关,我认为它们都围绕着相同的原则.
在使用JS多年之后,我今天决定真正开始学习JS的工作原理,而不是像在浏览器中运行的那样对待它.所以我开始深入研究jQuery代码,看看真正的JS开发人员如何使用langauge.就在那时我发现了一段看起来像下面代码的代码.注意,我把这个代码从另一个堆叠的帖子中删除了这里在Javascript中,你能扩展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
})();
Run Code Online (Sandbox Code Playgroud)
1为什么使用var myDOM =(function(){})()声明函数; 而不是var myDOM = function(){};
2为什么在myDOM函数中使用完全相同的名称声明另一个函数?为什么不将所有内部myDOM的逻辑放在外部myDOM函数中?
3为什么要明确地返回"this"?这本来是自动完成的,对吗?
4这里发生了什么?它是否返回内部myDOM的构造函数?如果是这样,为什么?
更新
所以现在大部分都有意义.关于#1,我认为myDOM被分配了=之后定义的函数,但事实并非如此.它被分配给函数返回的任何东西.这恰好是一个功能.
我还不清楚#3.是的,我理解使用这样的功能
console.log(MyDomConstruct('foo'))
Run Code Online (Sandbox Code Playgroud)
会显示'undefined'.但这不是它的使用方式.这几行就是这样的
return new MyDomConstruct(elems);
Run Code Online (Sandbox Code Playgroud)
如果声明像这样,我可以理解明确返回"this"
return MyDomConstruct(elems);
Run Code Online (Sandbox Code Playgroud)
但事实并非如此.
为什么使用var myDOM =(function(){})()声明函数; 而不是var myDOM = function(){};
这就是所谓的self-invoking anonymous function或self-executing anonymous function.它就是这样,它在运行时调用它自己.你还会看到这种模式:
(function($){
}(jQuery));
Run Code Online (Sandbox Code Playgroud)
在jQuery世界中有很多.同样的事情,在运行时函数调用自身并保证$符号jQuery在函数体内具有对象的引用.
在你的代码片段中,函数调用自身并返回myDOM一个函数引用.
为什么要使用完全相同的名称在myDOM函数中声明另一个函数?为什么不将所有内部myDOM的逻辑放在外部myDOM函数中?
这只是一个惯例.它可以被称为任何你想要的,也许作者认为这样做很方便.这种模式的原因是隐私和安全.通过返回内部myDOM引用closure,创建了a .所以后面宣布了类似的东西
var mytest = myDOM([]);
Run Code Online (Sandbox Code Playgroud)
你将无法访问MyDOMConstruct,但你的内部功能确实有权访问.这样你就可以保护你的方法和变量.它也被称为method pattern.在这种情况下总是很好的阅读Douglas Crockford: Javascript the good parts.
为什么明确地返回"这个"?这本来是自动完成的,对吗?
不,函数将undefined默认返回值.通过显式返回,this您可以chain使用类似的方法(来自上面的示例调用):
mytest.forEach([]).addStyles([]); ...
Run Code Online (Sandbox Code Playgroud)
因为在这种情况下,每个方法都返回调用对象myDOM.
这里发生了什么?它是否返回内部myDOM的构造函数?如果是这样,为什么?
我希望在这一点上应该清楚.
编辑
根据您的更新:
new MyDOMConstruct();
Run Code Online (Sandbox Code Playgroud)
生成一个inherits来自的新对象
MyDOMConstruct.prototype
Run Code Online (Sandbox Code Playgroud)
如果没有new keyword该this不会被绑定到新的对象.相反,它将绑定到全局对象(窗口),您将使用this.
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 ().
Run Code Online (Sandbox Code Playgroud)
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.
Run Code Online (Sandbox Code Playgroud)
所以内部对象可以被命名为任何东西,并且它可以被执行myDOM(),但是如果你命名内部函数blah,你仍然可以通过使用myDOM()...来执行它...这不是很清楚...更好地命名它.
3.为什么明确地返回"这个"?这本来是自动完成的,对吗?
不,如果你不写任何东西,Javascript会自动返回undefined.该MDC参考:.
返回this通常用于保留方法的上下文.它曾经使方法($(here).is().a().chain().of().methods())的链接成为可能.因此,链中的方法知道它正在运行的上下文.