jQuery设计原理-无new构建实例
jQuery无new构建实例
无new化构建
在jQuery中 $符号就是jQuery的别称
$()就是创立了jQuery的实例对象
实现
(function(root){ function jQuery() { return new jQuery.prototype.init(); }; // 在jQuery的原型上定义init方法 jQuery.prototype = { init: function() { }, css: function() { // 在jQuery原型上扩展的属性也会被共享到init的原型上 } } // 把jQuery的原型共享给init的原型 jQuery.prototype.init.prototype = jQuery.prototype; // 设置全局变量$和jQuery root.$ = root.jQuery = jQuery;})(this); // 把宿主对象window传进
共享原型设计
形容
如上, 在实现jQuery实例化的时候,我们直接调用$();
console.log($());
由于$()指向的是jQuery函数,所以相当于调用了jQuery函数;
// 设置全局变量$和jQuery; // $和window.jQuery指向的都是jQuery函数 root.$ = root.jQuery = jQuery;
jQuery作为构造函数直接被调用效果和普通函数呗调用一样,
所以无法生成有效实例;
处理方案:
只能把jQuery函数的返回值设成构造函数的实例;
function jQuery() { return new jQuery();};
但是这样做是不行的,很显著会造成死循环
所以jQuery采用的共享原型的设计模式, 即;
在jQuery函数的prototype上定义了init方法
// 在jQuery的原型上定义init方法 jQuery.prototype = { init: function() { } }
把jQuery的原型共享给init
// 把jQuery的原型共享给init的原型 jQuery.prototype.init.prototype = jQuery.prototype;
通过$()调用jQuery函数时返回一个init的实例
function jQuery() { return new jQuery.prototype.init(); };
给jQuery的prototype扩展属性的时候,因为原型共享,
所以init的原型上也会具备该扩展属性
jQuery.prototype = { init: function() { }, css: function() { // 在jQuery原型上扩展的属性也会被共享到init的原型上 } } console.log($());
123.png
以上就是jQuery无new实例化的实现
原型扩展设计见下图:
1122.png
extend函数源码解析
extend函数用法:
// 给任意对象扩展 var obj1 = { a:1, b:2 }; var obj2 = { c: 3 }; var res = $.extend(obj1, obj2); console.log(res); // ===> { a:1, b:2, c: 3 } console.log(obj1); // ===> { a:1, b:2, c: 3 } // 给$(jQuery)进行扩展 $.extend({ myMethod: function() { console.log('myMethod1'); } }) $.myMethod(); // myMethod1; // 给$(jQuery)的实例进行扩展 $.fn.extend({ myMethod: function() { console.log('myMethod2'); } }) $().myMethod(); // myMethod2;
extend函数用于给对象进行扩展,给jQuery提供了插件机制
- 可以给任意对象扩展
- 也可以给jQuery自身扩展
注:
// $.fn指向的就是$.prototype jQuery.fn = jQuery.prototype = { // ...... }
- extend再jQuery中之所以既能通过$.extend调用,
又能通过$().extend调用是由于在源码内部中实现了jQuery.fn.extend = jQuery.extend = function() { // ...... }
extend实现与分析
// extend jQuery.fn.extend = jQuery.extend = function() { var target = arguments[0] || {}; // target赋值为第一个参数,也就是要扩展的对象 var length = arguments.length; // 获取参数的个数 var i = 1; var deep = false; var options, name, copy, src, copyIsArray, clone; if(typeof target === 'boolean') { // 当传入第一个参数是boolean时 deep = target; // 把参数deep的值设置为target,即传入的第一个参数 target = arguments[1]; // 把target(需扩展的对象设置为第二个参数) i = 2; // i = 2,以便之后从第三个参数开始遍历 }; if(typeof target !== 'object') { // 验证传入的参数为obj target = {}; }; if(length === i) { // 假如只有一个参数,则extend方法为jQuery内部的扩展 target = this; // 把target的引用设置为this,指向$或者者$() i--; }; // 浅拷贝 for( ;i < length; i++) { // boolean参数和所需要扩展的对象的属性无需遍历 if((options = arguments[i]) !==null) { for(name in options) { copy = options[name]; src = target[name]; // 假如需要深拷贝,并且options的属性对应的是对象或者数组时 if(deep && (jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)))) { if(copyIsArray) { copyIsArray = false; //copyIsArray不重置会影响下一次循环的判断; clone = src && jQuery.isArray(src) ? src : []; } else { clone = src && jQuery.isPlainObject(src) ? src : {}; } target[name] = jQuery.extend(deep, clone, copy); } else if(copy !== undefined) { target[name] = copy; }; }; }; }; return target; } jQuery.extend({ isPlainObject: function(obj) { // 判断传入参数的数据类型能否是obj return toString.call(obj) === '[object Object]' }, isArray: function(arr) { // 判断传入参数的数据类型能否是数组 return toString.call(arr) === '[object Array]' } });
说明
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » jQuery设计原理-无new构建实例
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » jQuery设计原理-无new构建实例