读书人

发个JS练手创作简单的OO封装

发布时间: 2013-03-14 10:33:15 作者: rapoo

发个JS练手作品,简单的OO封装
最近翻书复习了下基础知识,感觉书上的面向对象的例子用起来不是很顺手
所以自己改了下,纯粹练手,有意见的请拍砖,当然最好能给出更好的例子。

var $class = (function(){       
var guid = 0,
classMap = {},
caller = null,
callStack = [];

return {
create : createClass
}

//------------------------[辅助函数部分]------------------------

/**
* 创建新类.
* @param {constructor}superClass 超类构造器,该类必须由$class.create创建
* @param {Json}proto 类原型
* @return {constructor}
*/
function createClass(superClass, proto){
var isSuperValid = superClass instanceof Function
&& superClass.prototype
&& superClass.prototype.init instanceof Function;

superClass = isSuperValid ? superClass : null;

var superProto = superClass ? superClass.prototype : null;

//定义类构造函数
var klass = function() {
var args = [].slice.call(arguments);

//执行父类构造函数.
if(superClass){
superClass.apply(this, args);


}

//若自己的原型中有init方法,执行init
if(klass.prototype.hasOwnProperty('init')){
klass.prototype.init.apply(this, args);
}
};

//定义类原型
var klassProto = getClassProto(superProto, proto);
klassProto.constructor = klass;
klass.prototype = klassProto;

//返回类
return klass;
}

/**
* 获取类原型.
* @param {json}superProto 超类原型
* @param {Json}overwrites 需要重写方法
* @return {json}
*/
function getClassProto(superProto, overwrites) {
var i, F, proto, classId = getGuid();

if(superProto){
F = function(){};
F.prototype = superProto;
proto = new F();
}else{
proto = getDefaultProto();
}



//用overwrites中方法覆盖原型中的方法
for(i in overwrites){
if(overwrites.hasOwnProperty(i)){
proto[i] = overwrites[i];
}
}

//修复IE中for in不能遍历toString、valueOf等属性的Bug
if(document.all){
var len, method, methods = ['toString', 'valueOf'];
for(i=0, len = methods.length; i < len; i++){
method = methods[i];
if( overwrites.hasOwnProperty(method) ){
proto[method] = overwrites[method];
}
}
}

//注册类关系
proto.classId = classId;
regClass(proto, superProto);

//确保原型中含有必要的原型方法
addMastHasMethods(proto);

return proto;
}

/**
* 获取默认原型.
* @return {json}
*/
function getDefaultProto(){
return {
init : function(){},


callSuper : callSuper
};
}

/**
* 调用超类方法.
* @param {String}methodName 方法名
* @return
*/
function callSuper(methodName){
caller = (caller === null ? this : caller);

var curClsId = callStack.length > 0
? callStack[callStack.length - 1]
: this.classId;

var args = [].slice.call(arguments, 1),
parent = getParent(curClsId),
ret;

if(parent && parent[methodName]){
callStack.push(parent.classId);

try{
ret = parent[methodName].apply(caller, args);
}catch(e){
alert(e);
}

callStack.pop();
}

//调用完毕后将调用上下文清空
if(callStack.length === 0){
caller = null;
}

return ret;


}

/**
* 将类信息注册到类记录表中.
* @param {json}proto 类原型.
* @param {json}parent 超类原型
*/
function regClass(proto, superProto){
var classId = proto.classId;

classMap[classId] = {
id : classId,
proto : proto,
parent: superProto
};
}

/**
* 检查原型链中是否有必须要实现的方法,没有的话,向原型中添加.
* @param {json}proto
*/
function addMastHasMethods(proto){
var i, dftProto = getDefaultProto();
for(i in dftProto){
if(dftProto.hasOwnProperty(i) && !proto[i]){
proto[i] = dftProto[i];
}
}
}

/**
* 获取guid.
* @return {int}
*/
function getGuid(){
return guid++;
}

/**
* 获取超类原型.
* @param {int}classId 类ID
* @return {json} 超类原型, 若存在返回null.
*/
function getParent(classId){


var record = classMap[classId];
return record ? record.parent : null;
}
})();

var Man = $class.create(null, {
init : function(cfg){
this.name = cfg.name;
this.age = cfg.age;
},

say : function(){
alert('my name is:' + this.name + ", " + this.age);
},

toString : function(){
return (
'name: ' + this.name
+ ', age: ' + this.age
);
}
});

var Student = $class.create(Man, {
init : function(cfg){ //执行此方法前会自动调用Man.init
this.stuNum = cfg.stuNum;
},

say : function(){
this.callSuper('say'); //调用父类方法
alert("i'm a student, my student number is " + this.stuNum);
},

toString : function(){
return (
this.callSuper('toString')
+ ', stuNum: ' + this.stuNum
);
}
});

window.onload = function(){
var m1 = new Man({name : '张三', age: 20}),
s1 = new Student({
name : '王五',
age : 22,
stuNum : 'no-1'
});

m1.say();
s1.say();
alert(m1.toString() + "\n" + s1.toString());
};


------解决方案--------------------


楼主好人,copy学习下
[解决办法]
发个JS练手创作,简单的OO封装
[解决办法]
$class.create(null, {
init : function(cfg){
this.name = cfg.name;
this.age = cfg.age;
}

建议把这个null省略掉
[解决办法]
一直不怎么喜欢以OO方式写JS,不过大势所趋,代码多了也确实OO会方便些

收藏以备深入学习发个JS练手创作,简单的OO封装
[解决办法]
喜欢OO也喜欢XX
[解决办法]
楼主算法的目的是什么?
[解决办法]
算法核心部分应该就是继承的功能,LZ应该是出于这个目的

尽可能的向OO靠齐
[解决办法]
支持,这么写一边自己对OO又加深了印象
[解决办法]
楼看过mootool源码吧。
[解决办法]
要需要在重写的方法中引用
父类的方法。
[解决办法]
姑且不说别的 代码写的很规整 境界很高深 我无比敬佩 这才是一个优秀的coding开发人员 我顶你~~~
[解决办法]
楼主强大,咱JS还在入门中,表示看不懂这些
[解决办法]
这。。。。好深奥啊,新手表示看不懂
[解决办法]
楼主应该写点注释
[解决办法]
谢谢分享。。。。。。。。。。。。。
[解决办法]


[解决办法]
太高深了
[解决办法]
哎。看不懂呐。




--------------------------------------帅签分割线-------------------------------------------------
发个JS练手创作,简单的OO封装
[解决办法]
学习了。
[解决办法]
这么写主要是为了解决JS继承中一个很麻烦的问题:
你既要重写父类的方法,要需要在重写的方法中引用
父类的方法。
===========================
function merge(a, b) //ensure a and b are both 'function' type
{
if(a && a != b)
{
var merged = function(){
this.__super__ = arguments.callee.__super__;
return b.apply(this, arguments);
}
merged.__super__ = a;
return merged;
}
return a;
}
在getClassProto中的循环检查同名函数然后merge。
在实例中可以直接在各个方法内直接this.__super__(1,2,3);


省去callStack另外init也能__super__
如say : function(str)
{
this.__super__();
alert('say:' + str);
}

[解决办法]
mark
[解决办法]
学习一下
[解决办法]
楼主看的什么书啊?
[解决办法]
楼主写点注释啊,要不新手看不懂。
[解决办法]
厉害。oo确实使用很方便。
oo 再加上VS2010,那真是完美了






-----------------------------

新版老虎插件即将登场:发个JS练手创作,简单的OO封装
[解决办法]
牛人呀
[解决办法]
发个JS练手创作,简单的OO封装
[解决办法]
不知道js面向对象是不是真的大势所趋
[解决办法]
看不懂啊看不懂。。。
[解决办法]



(function(){
var Base = window.Base = Base
[解决办法]
{
///summary: 静态方法,创建抽象类
create: function () {
return function () {
this.initialize.apply(this, arguments);
}
},
///summary: 静态方法,实现继承,允许重载
extend: function () {
if (1 == arguments.length) {
for (var p in arguments[0]) this[p] = arguments[0][p];
return this;
};
for (var p in arguments[1]) arguments[0][p] = arguments[1][p];
return arguments[0];
},
///summary: Cookie类
Cookie: function () {
var Cookie = Base.create();
Cookie.prototype = {
initialize: function () { },
///写cookie
setCookie: function (name, value) {


var date = new Date();
date.setTime(date.getTime() + 30 * 24 * 3066 * 1000);
document.cookie = name + "=" + value + ";expires=" + date.toGMTString()
},
///读cookie
getCookie: function (name) {
var CookieArray = document.cookie.split(";");
for (var i = 0; i < CookieArray.length; i++) {
var arr = CookieArray[i].split("=");
if (arr[0] == name) {
return arr[1];
break;
}
}
},
///清除cookie
clearCookie: function (name) {
document.cookie = name + "=''; expires=Thu, 01-Jan-70 00:00:01 GMT";
}
}
return new Cookie();
}
};
})();


[解决办法]
楼主强大
[解决办法]
该回复于2012-05-19 10:12:41被版主删除
[解决办法]
留下脚印,copy
[解决办法]
向老鸟看齐,顶楼主
[解决办法]


mark & up

留备以后学习
[解决办法]
看不太懂,但是还是认真看完了,
[解决办法]
厉害啊!不错的

读书人网 >JavaScript

热点推荐