函数可以实现类
var aQuery = function(selector, context) { //构造函数 } aQuery.prototype = { //原型 name:function(){}, age:function(){} } var a = new aQuery(); a.name();
1、jQuery的无new构建
jQuery没有使用new运行符将jQuery显示的实例化
var aQuery = function(selector, context) { return new aQuery(); } aQuery.prototype = { name:function(){}, age:function(){} }
通过new aQuery(),虽然返回的是一个实例,但是也能看出很明显的问题,死循环了!
在javascript中实例this只跟原型有关系,那么可以把jQuery类当作一个工厂方法来创建实例,把这个方法放到jQuery.prototye原型中
var aQuery = function(selector, context) { return aQuery.prototype.init(); } aQuery.prototype = { init:function(){ return this; } name:function(){}, age:function(){} }
var aQuery = function(selector, context) { return aQuery.prototype.init(); } aQuery.prototype = { init: function() { this.age = 18 return this; }, name: function() {}, age: 20 } aQuery().age //18
jQuery = function( selector, context ) { // The jQuery object is actually just the init constructor 'enhanced' return new jQuery.fn.init( selector, context, rootjQuery ); },
很明显通过实例init函数,每次都构建新的init实例对象,来分隔this,避免交互混淆 。那么既然都不是同一个对象那么肯定又出现一个新的问题
var aQuery = function(selector, context) { return new aQuery.prototype.init(); } aQuery.prototype = { init: function() { this.age = 18 return this; }, name: function() {}, age: 20 } //Uncaught TypeError: Object [object Object] has no method 'name' console.log(aQuery().name())
// Give the init function the jQuery prototype for later instantiation jQuery.fn.init.prototype = jQuery.fn;
jQuery的原型对象覆盖了init构造器的原型对象
var aQuery = function(selector, context) { return new aQuery.prototype.init(); } aQuery.prototype = { init: function() { return this; }, name: function() { return this.age }, age: 20 } aQuery.prototype.init.prototype = aQuery.prototype; console.log(aQuery().name()) //20
3、链式调用
aQuery().init().name() // 分解 a = aQuery(); a.init() a.name()
实现链式的基本条件就是实例this的存在,返回当前实例的this,从而又可以访问自己的原型了
aQuery.prototype = { init: function() { return this; }, name: function() { return this } }
最糟糕的是所有对象的方法返回的都是对象本身,也就是说没有返回值,这不一定在任何环境下都适合。 Javascript是无阻塞语言,所以他不是没阻塞,而是不能阻塞,所以他需要通过事件来驱动,异步来完成一些本需要阻塞进程的操作,这样处理只是同步链式,异步链式jquery从1.5开始就引入了Promise,jQuery.Deferred。
4、插件借口
jQuery.extend = jQuery.fn.extend = function() {}
(function( window, undefined ) { // jquery code })(window);
(function( window, undefined ) { var jQuery = (function() { // 构建jQuery对象 var jQuery = function( selector, context ) { return new jQuery.fn.init( selector, context, rootjQuery ); } // jQuery对象原型 jQuery.fn = jQuery.prototype = { constructor: jQuery, init: function( selector, context, rootjQuery ) { // selector有以下7种分支情况: // DOM元素 // body(优化) // 字符串:HTML标签、HTML字符串、#id、选择器表达式 // 函数(作为ready回调函数) // 最后返回伪数组 } }; // Give the init function the jQuery prototype for later instantiation jQuery.fn.init.prototype = jQuery.fn; // 合并内容到第一个参数中,后续大部分功能都通过该函数扩展 // 通过jQuery.fn.extend扩展的函数,大部分都会调用通过jQuery.extend扩展的同名函数 jQuery.extend = jQuery.fn.extend = function() {}; // 在jQuery上扩展静态方法 jQuery.extend({ // ready bindReady // isPlainObject isEmptyObject // parseJSON parseXML // globalEval // each makeArray inArray merge grep map // proxy // access // uaMatch // sub // browser }); // 到这里,jQuery对象构造完成,后边的代码都是对jQuery或jQuery对象的扩展 return jQuery; })(); window.jQuery = window.$ = jQuery; })(window);