;(function(global, factory){
factory(global);
}(typeof window !== "undefined" ? window : this, function(window, noGlobal) {
var jQuery = function (selector, context) {
return new jQuery.fn.init(selector, context);
}
jQuery.fn = jQuery.prototype = {};
return jQuery;
}));
任何库与框架设计的第一个要点就是解决命名空间与变量污染的问题。jQuery就是利用了JavaScript函数作用域的特性,采用立即调用表达式包裹了自身的方法来解决这个问题。
jQuery的立即调用函数表达式的写法有三种:
写法1:
(function(window, factory) {
factory(window);
}(this, function() {
return function() {
//jQuery的调用
}
}))
可以看出上面的代码中嵌套了2个函数,而且把一个函数作为参数传递到另一个函数中并且执行,这种方法有点复杂,我们简化一下写法:
写法2:
var factory = function() {
return function() {
//执行方法
}
}
var jQuery = factory();
上面的代码效果和方法1是等同的,但是这个factory有点变成了简单的工厂方法模式,需要自己调用,不像是一个单例的jQuery类,所以我们需要改成“自执行”,而不是另外调用。
写法3:
(function(window, undefined) {
var jQuery = function() {}
// ...
window.jQuery = window.$ = jQuery;
})(window);从上面的代码可看出,自动初始化这个函数,让其只构建一次。详细说一些这种写法的优势:
- window和undefined都是为了减少变量查找所经过的scope作用域。当window通过传递给闭包内部之后,在闭包内部使用它的时候,可以把它当成一个局部变量,显然比原先在window scope下查找的时候要快一些。
- undefined也是同样的道理,其实这个undefined并不是JavaScript数据类型的undefined,而是一个普普通通的变量名。只是因为没给它传递值,它的值就是undefined,undefined并不是JavaScript的保留字。
为什么要传递undefined?
JavaScript中的undefined并不是作为关键字,因此可以允许用户对其赋值。
总结:全局变量是魔鬼,匿名函数可以有效地保证在页面上写入JavaScript,而不会造成全局变量的污染,通过小括号,让其加载的时候立即初始化,这样就形成了一个单例模式的效果从而只会执行一次。