1.Jquery的构建方式
Jquery的构建方式有两种,一种是用new 构建,另一种是直接调用函数构建
<div class="test"></div>
<script type="text/javascript">
var q = new $('.test')
var s = $('.test')
console.log(s)
console.log(q)
</script>
将s 和q打印出来可以得出s和q的数据结构是相同的,但两者是不相等的。

- Jquery的函数构建
安装Jquery的书写方式,我们可以使用类似
()应该是返回类的实例才对
(function (window, undefined) {
var jQuery = function (selector, context) {
return new jQuery
}
})(window)
通过上面的例子可以看出,如果采用new jQuery的构建方式虽然会返回一个时例,但会出现死循环情况
- 返回一个正确的实例
在jquery中jQuery函数是返回new jquery.fn.init(selector, context),相当于把jQuery函数看出一个工厂方法,从上面的分析得知,new jquery.fn.init(selector, context)应与new jQuery相等,才能实现两种构建方式,所以两者的原型应该相等,即jquery.fn.init.prototype==jQuery.prototype。
(function (window, undefined) {
var jQuery = function (selector, context) {
return new jquery.fn.init(selector, context)
}
jquery.fn = jQuery.prototype = {
init: function (selector, context) {
},
}
jQuery.fn.init.prototype=jQuery.fn//jQuery.fn==jQuery.prototype
})()
#2.链式调用
DOM链式调用的处理能够节约代码,所返回的都是同一个对象,可以提高代码的效率。在jquery中实现链式调用是通过简单扩展原型方法并通过return this的形式来实现跨浏览器的链式调用
jQuery.prototype = {
init: function() {
return this;
},
name: function() {
return this
}
}
3.val的实现
在jquery中val()没有传参时是获取相关的值,如果有传参,表示进行赋值。实现该功能主要运用的是函数的重载。函数的重载是指函数名相同,但传递的参数不同。但在js中是没有函数的重载概念的,后声明的函数会覆盖签名声明的函数,以下是jq的实现方式
(function (window, undefined) {
function addMethod(obj, name, f) {
var old = obj[name]
obj[name] = function () {
if (f.length === arguments.length) {
return f.apply(this, arguments)
} else {
return old.apply(this, arguments)
}
}
}
var people = {
name: ['Zhang san', 'Li si'],
}
addMethod(people, 'find',find1 )
var find1=function () {
console.log('无参数')
return this.values
}
addMethod(people, 'find', find2)
var find2=function (firstname) {
console.log('一个参数')
var ret = []
for (var i = 0; i < this.values.length; i++) {
if (this.name[i].indexOf(firstname) === 0) {
ret.push(this.name[i])
}
}
return ret
}
console.log(people.find())
console.log(people.find('Zhang'))
})(window)
- 实现的关键是old,old相当于指针,每一次都指向上一次调用的函数。
- obj[name]函数中的this是指向obj的,arguments是函数f的实参,f.length是函数f的形参
- 第一次调用addMethod的时候,old=>undefined,obj[name]=>find1;因为old在obj[name]函数中调用了,所以此时obj不会被垃圾回收,会继续保存,相当于必包。
- 第二次调用addMethod,old=>find1,obj[name]=>find2.这时的old指向上一次调用的函数,又是闭包,继续保存。 -内存中实际上有两个个 obj[name]和old,因为两次method的内存都没有删除,实现了两个个函数共存,用old把他们链接起来
- people.find() 的时候,就会最先调用最后一次调用method时定义的function,如果参数个数相同 也就是 arguments.length === fnc.length 那么就执行就好了,也不用找别的函数了,如果不相同的话,那就得用到old了 return old.apply(this,arguments); old指向的是上次addMethod调用时定义的函数,所以我们就去上一次的找,如果找到了,继续执行 arguments.length === fnc.length 如果找不到,再次调用old 继续向上找,只要你定义过,肯定能找到的, 总结:运用闭包的原理使两个函数共存于内存中,old相当于一个指针,指向上一次定义的function,每次调用的时候,决定是否需要寻找。