作者:zhanhailiang 日期:2013-01-04
JS可以依赖原型链来实现OO语言中的继承概念。
原型链的基本思想是利用原型prototype让一个引用类型继承另一个引用类型的属性和方法。实现原型链的基本模式如下:
function SuperType() {
this.property = true;
}
SuperType.prototype.getSuperValue = function() {
return this.property;
};
function SubType() {
this.subProperty = false;
}
// 继承SuperType
SubType.prototype = new SuperType();
SubType.prototype.getSubValue = function() {
return this.subProperty;
};
原型链继承的问题很明显,主要就是包含引用类型值的原型。由此例可知,父类的属性会被所有子类实例所共享。(解决方法可以采用 “借用构造函数”来消除该问题)
接下来我们将利用原型链继承来分析jQuery.sub的实现:
// jQuery.sub可创建一个新的jQuery副本,不影响原有的jQuery对象。
// 有两个具体使用jQuery.sub()的应用场景。
// 1.提供完全没有破坏jQuery原有一切的方法;
// 2.用于帮助做jQuery插件封装和基本命名空间。
// 注:jQuery.sub()不会做任何特殊的隔离,所有关于jQuery的sub版本的方法将仍然指向原来的jQuery。
// (绑定和触发仍将通过主jQuery的事件,数据将通过主绑定的元素的jQuery,Ajax的查询和活动将通过主jQuery的运行,等等)
jQuery.sub = function() {
function jQuerySub( selector, context ) {
return new jQuerySub.fn.init( selector, context );
}
// this 指向 jQuery
jQuery.extend( true, jQuerySub, this );
jQuerySub.superclass = this; // jQuery是jQuerySub的父类
jQuerySub.fn = jQuerySub.prototype = this(); // jQuerySub继承jQuery的方法
jQuerySub.fn.constructor = jQuerySub; // jQuerySub instanceOf jQuerySub === true
jQuerySub.sub = this.sub;
// jQuerySub.fn.init是jQuerySub本质的构造函数,就象jQuery.fn.init是jQuery本质的构造函数做法相似
jQuerySub.fn.init = function init( selector, context ) {
if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {
context = jQuerySub( context );
}
// jQuery.fn.init创建新的jQuery的副本
return jQuery.fn.init.call( this, selector, context, rootjQuerySub );
};
jQuerySub.fn.init.prototype = jQuerySub.fn;
var rootjQuerySub = jQuerySub(document);
return jQuerySub; // 返回jQuerySub对象
};
接下来给出官方文档给出来的三个例子:
Example: 添加一个jQuery的方法,以便它不会受到外部分。
(function(){
var sub$ = jQuery.sub();
sub$.fn.myCustomMethod = function(){
return 'just for me';
};
sub$(document).ready(function() {
sub$('body').myCustomMethod() // 'just for me'
});
})();
// 注意在jQuery.sub的原型链jQuery.sub.fn上添加方法myCustomMethod并不会出现在jQuery.fn上,
// 从源码来理解,可以将jQuery.sub看做是jQuery的子类,而myCustomMethod方法只定义在jQuery.sub上
typeof jQuery('body').myCustomMethod; // undefined
Example: 改写一些jQuery的方法,以提供新的功能。
(function() {
var myjQuery = jQuery.sub();
myjQuery.fn.remove = function() {
// New functionality: Trigger a remove event
this.trigger("remove");
// Be sure to call the original jQuery remove method
return jQuery.fn.remove.apply( this, arguments );
};
myjQuery(function($) {
$(".menu").click(function() {
$(this).find(".submenu").remove();
});
// A new remove event is now triggered from this copy of jQuery
$(document).bind("remove", function(e) {
$(e.target).parent().hide();
});
});
})();
// Regular jQuery doesn't trigger a remove event when removing an element
// This functionality is only contained within the modified 'myjQuery'.
Example: 创建一个插件,它返回插件的具体办法。
(function() {
// Create a new copy of jQuery using sub()
var plugin = jQuery.sub();
// Extend that copy with the new plugin methods
plugin.fn.extend({
open: function() {
return this.show();
},
close: function() {
return this.hide();
}
});
// Add our plugin to the original jQuery
jQuery.fn.myplugin = function() {
this.addClass("plugin");
// Make sure our plugin returns our special plugin version of jQuery
return plugin( this );
};
})();
$(document).ready(function() {
// Call the plugin, open method now exists
$('#main').myplugin().open();
// Note: Calling just $("#main").open() won't work as open doesn't exist!
});