-
立即调用表达式 任何库与框架设计的第一个要点就是解决命名空间与变量污染的问题。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);查看全部
-
静态与实例方法共享设计 jQuery在接口的设计: 遍历方法: $(".aaron").each() //作为实例方法存在 $.each() //作为静态方法存在 这是最常见的遍历方法,第一条语句是给有指定的上下文调用的,就是(".aaron")获取的DOM合集,第二条语句$.each()函数可用于迭代任何集合,无论是“名/值”对象(JavaScript对象)或数组。在迭代数组的情况下,回调函数每次都会传递一个数组索引和相应的数组值作为参数。本质上来说2个都是遍历,那么我们是不是要写2个方法呢? 我们来看看jQuery的源码: jQuery.prototype = { each: function( callback, args ) { return jQuery.each( this, callback, args ); } } 实例方法取于静态方法,换句话来说这是静态与实例方法共享设计,静态方法挂在jQuery构造器上,原型方法挂在哪里呢? 我们上节不是讲了内部会划分一个新的构造器init吗?jQuery通过new原型prototype上的init方法当作构造器,那么init的原型链方法就是实例的方法了,所以jQuery通过2个构造器划分2种不同的调用方式一种是静态,一种是原型。 方法是共享的,并且实例方法取于静态方法,2个构造器是完全隔离的 ,这个要如何处理? 看看jQuery给的方案: 画龙点睛的一处init.prototype = jQuery.fn,把jQuery.prototype原型的引用赋给jQuery.fn.init.prototype的原型,这样就把2个构造器的原型给关联起来了。 ajQuery.fn = ajQuery.prototype = { name: 'aaron', init: function(selector) { this.selector = selector; return this; }, constructor: ajQuery } ajQuery.fn.init.prototype = ajQuery.fn查看全部
-
var $$ = ajQuery = function(selector) { this.selector = selector; return new ajQuery(selector); } 是一个死循环,为了避免死循环 var $$ = ajQuery = function(selector) { //把原型上的init作为构造器 return new ajQuery.fn.init( selector ); } init是ajQuery原型上作为构造器的一个方法,所以通过new ajQuery.fn.init( selector );之后,那么init的this就不再是aJQuery了,init的this就完全引用不到aJQuery的原型了,所以这里通过new把init方法与aJQuery给分离成2个独立的构造器了.查看全部
-
jQuery为了避免出现这种死循环的问题,采取的手段是把原型上的一个init方法作为构造器 var $$ = ajQuery = function(selector) { //把原型上的init作为构造器 return new ajQuery.fn.init( selector ); } ajQuery.fn = ajQuery.prototype = { name: 'aaron', init: function() { console.log(this) }, constructor: ajQuery } 这样确实解决了循环递归的问题,但是又问题来了,init是ajQuery原型上作为构造器的一个方法,那么其this就不是ajQuery了,所以this就完全引用不到ajQuery的原型了,所以这里通过new把init方法与ajQuery给分离成2个独立的构造器。查看全部
-
分离构造器 通过new操作符构建一个对象,一般经过四步: A.创建一个新对象 B.将构造函数的作用域赋给新对象(所以this就指向了这个新对象) C.执行构造函数中的代码 D.返回这个新对象 最后一点就说明了,我们只要返回一个新对象即可。其实new操作符主要是把原型链跟实例的this关联起来,这才是最关键的一点,所以我们如果需要原型链就必须要new操作符来进行处理。否则this则变成window对象了。 我们来剖析下jQuery的这个结构,以下是我们常见的类式写法: var $$ = ajQuery = function(selector) { this.selector = selector; return this } ajQuery.fn = ajQuery.prototype = { selectorName:function(){ return this.selector; }, constructor: ajQuery } var a = new $$('aaa'); //实例化 a.selectorName() //aaa //得到选择器名字 首先改造jQuery无new的格式,我们可以通过instanceof判断this是否为当前实例: var $$ = ajQuery = function(selector) { if(!(this instanceof ajQuery)){ return new ajQuery(selector); } this.selector = selector; return this } 但是注意千万不要像下面这样写: var $$ = ajQuery = function(selector) { this.selector = selector; return new ajQuery(selector); } Uncaught RangeError: Maximum call stack size exceeded 这样会无限递归自己,从而造成死循环并且溢出。查看全部
-
jQuery对象的构建如果在性能上考虑,所以就必须采用原型式的结构: jQuery = function( selector, context ) { return new jQuery.fn.init( selector, context ); } jQuery.fn = jQuery.prototype = { init:function(){ return this }, jquery: version, constructor: jQuery, ……………… } var a = $() ; 使用原型结构,性能上是得到了优化,但是ajQuery类这个结构与目标jQuery的结构的还是有很大不一致: ☑ 没有采用new操作符; ☑ return返回的是一个通过new出来的的对象 。查看全部
-
函数在充当类的构造器时,原型prototype是一个重要的概念。prototype是构造函数的一个属性, 该属性指向一个对象。而这个对象将作为该构造函数所创建的所有实例的基引用(base reference), 可以把对象的基引用想像成一个自动创建的隐藏属性。 当访问对象的一个属性时, 首先查找对象本身, 找到则返回;若不, 则查找基引用指向的对象的属性(如果还找不到实际上还会沿着原型链向上查找, 直至到根)。 只要没有被覆盖的话, 对象原型的属性就能在所有的实例中找到。 类一: function ajQuery() { this.name = 'jQuery'; this.sayName = function(){ return this.name } var a = new ajQuery() var b = new ajQuery() var c = new ajQuery() 类二: function ajQuery() { this.name = 'jQuery' } ajQuery.prototype = { sayName: function() { return this.name } } var a = new ajQuery() var b = new ajQuery() var c = new ajQuery() 类一与类二产生的结构几乎是一样的,而本质区别就是:类二new产生的a、b、c三个实例对象共享了原型的sayName方法,这样的好处节省了内存空间,类一则是要为每一个实例复制sayName方法,每个方法属性都占用一定的内存的空间,所以如果把所有属性方法都声明在构造函数中,就会无形的增大很多开销,这些实例化的对象的属性一模一样,都是对this的引用来处理。除此之外类一的所有方法都是拷贝到当前实例对象上。类二则是要通过scope连接到原型链上查找,这样就无形之中要多一层作用域链的查找了。查看全部
-
如果我们需要同时使用jQuery和其他JavaScript库,我们可以使用 $.noConflict()把$的控制权交给其他库。旧引用的$ 被保存在jQuery的初始化; noConflict() 简单的恢复它们。 通过类似swap交换的概念,先把之前的存在的命名空间给缓存起来,通过对比当前的命名空间达到交换的目的,首先,我们先判断下当前的的$空间是不是被jQuery接管了,如果是则让出控制权给之前的_$引用的库,如果传入deep为true的话等于是把jQuery的控制权也让出去了。 如果不通过noConflict处理的话其后果可想而知,香喷喷的$大家都“觊觎已久”。查看全部
-
jQuery多库共存处理 多库共存换句话说可以叫无冲突处理。 总的来说会有2种情况会遇到: 1、$太火热,jQuery采用$作为命名空间,不免会与别的库框架或者插件相冲突。 2、jQuery版本更新太快,插件跟不上,导致不同版本对插件的支持度不一样。 出于以上的原因,jQuery给出了解决方案–– noConflict函数。 引入jQuery运行这个noConflict函数将变量$的控制权让给第一个实现它的那个库,确保jQuery不会与其他库的$对象发生冲突。 在运行这个函数后,就只能使用jQuery变量访问jQuery对象。例如,在要用到$("aaron")的地方,就必须换成jQuery("aaron"),因为$的控制权已经让出去了。 使用DEMO: jQuery.noConflict(); // 使用 jQuery jQuery("aaron").show(); // 使用其他库的 $() $("aaron").style.display = ‘block’; 这个函数必须在你导入jQuery文件之后,并且在导入另一个导致冲突的库之前使用。当然也应当在其他冲突的库被使用之前,除非jQuery是最后一个导入的。 由于比较简单,我们直接上代码解说: Var _jQuery = window.jQuery, _$ = window.$; jQuery.noConflict = function( deep ) { if ( window.$ === jQuery ) { window.$ = _$; } if ( deep && window.jQuery === jQuery ) { window.jQuery = _jQuery; } return jQuery; };查看全部
-
一个是ready一个是load,这两个到底有什么区别呢? ready与load谁先执行: 大家在面试的过程中,经常会被问到一个问题:ready与load那一个先执行,那一个后执行?答案是ready先执行,load后执行。 DOM文档加载的步骤: 要想理解为什么ready先执行,load后执行就要先了解下DOM文档加载的步骤: (1) 解析HTML结构。 (2) 加载外部脚本和样式表文件。 (3) 解析并执行脚本代码。 (4) 构造HTML DOM模型。//ready (5) 加载图片等外部文件。 (6) 页面加载完毕。//load 从上面的描述中大家应该已经理解了吧,ready在第(4)步完成之后就执行了,但是load要在第(6)步完成之后才执行。查看全部
-
回溯处理: .preObject() .end() .addBack()查看全部
-
jQuery插件的两种开发方式: (1)挂的jQuery命名空间下人全局函数,也可称为静态方法; (2)jQuery对象级别人方法,即挂的jQuery原型下的方法,这样通过选择器获取人jQuery对象实例也可以共享该方法。 接口:$.extend(target, [object1], [objectN]); 接口使用: jQuery.extend({ data: function() {}, removeData: function() {} }); jQuery.fn.extend({ data: function() {}, removeData: function() {} }); jQuery.extend调用的时候上下文指的是jQuery构造器,而jQuery.fn.extend调用人时候上下文指向的是jQuery构造器人实例对象了。查看全部
-
实现链式调用的原理是在方法内部返回当前这个实例对象this。 优点:能够节省代码量,提高代码人效率,代码看起来更简洁。 缺点:所有对象的方法都返回this,就高不能饿自己的返回值,不一定适合所有场合。查看全部
-
通过原型传递,实现实例方法和静态方法共享设计。查看全部
-
使用$.noConflict();让出$的控制权,可以通过闭包隔离,将$转为局部变量使用。查看全部
举报
0/150
提交
取消