jq源码的初步了解
jq整体是一个立即执行函数。
思考问题:如何封闭作用域,如何暴露变量,无new构造,链式调用(关键句:你是我爸爸,我也是你爸爸),公有原型思想
思考问题一:封闭作用域
立即执行函数:通过定义一个匿名函数,创建了一个新的函数作用域,相当于创建了一个“私有”的命名空间,该命名空间的变量和方法,不会破坏污染全局的命名空间。
思考问题二:jq实现变量暴露在全局(例如$.(xxx))
(function () { //立即执行函数私有化变量,防止与js代码之间相互变量的污染;
var a = 13;
unction jQuery(str) {
console.log(str);
console.log(a);
}
window.$ = window.jQuery = jQuery; //暴露jQuery,$;
}());
jQuery('lalala'); //这个时候我们可以全局直接用jQuery()调用里面的方法;
此时若是想访问全局对象,将全局对象以参数形式传进去即可。
(function(window,undefind){
//jQuery code
}(window))
其中window即是全局对象。作用域隔离非常重要,是一个JS框架必须支持的功能,jQuery被应用在成千上万的JavaScript程序中,必须确保jQuery创建的变量不能和导入他的程序所使用的变量发生冲突。
思考问题三:无new构造实现(将方法写在jq的原型上)
function jQuery(str) {
return new jQuery.prototype.init(str)
}
jQuery.fn = jQuery.prototype = {
init: function (str) {
console.log('init');
},
html: function (str) {
console.log('html')
},
css: function (str) {
console.log('css')
}
}
jQuery();
创建一个jq函数,里面返回他原型链的属性(经过new出来的)
思考问题四:链式调用(关键点在返回值和原型继承)
function jQuery(str) {
jQuery.prototype.init.prototype = jQuery.prototype;
return new jQuery.prototype.init(str);
}
jQuery.fn = jQuery.prototype = {
init: function () {
console.log('init');
return this;
},
html: function () {
console.log('html');
return this;
},
css: function () {
console.log('css');
return this;
}
}
jQuery().html().css()
实现链式调:
执行jQuery()函数,实际是执行了jQuery原型上的init属性(属性值为函数)。在后面继续调用htnl和css方法,这里会有一个问题。因为html和css是jQuery原型上的属性不是init属性上的属性,所以这里我们可以把init原型链的指向给修改了,实现了把jQuery上的方法挂到init上。
当然,我们调用完init属性后,需要把init给返回(jQuery().html()--->init().html)
function jQuery(str) {
jQuery.prototype.init.prototype = jQuery.prototype;
return new jQuery.prototype.init(str);
}
jQuery.fn = jQuery.prototype = {
init: function () {
console.log('init');
console.log(this);
return this;
},
html: function () {
console.log('html')
console.log(this);
return this;
},
css: function () {
console.log('css')
console.log(this);
return this;
}
}
jQuery().html().css()
可以执行以上代码。打印出来的this值为init()这个函数方法。
通过以上,实现了链式调用(核心在于入口函数init对jQuery原型的继承,和返回值的设定。)