面向对象Javascript核心支持代码

JQury框架绝对是页面开发的首选,代码短小强悍,缺点就是面向对象特性不足,所幸有不少插件!至于Ext就是一个庞然大物了,高度面向对象,类似于MFC的庞大API和控件库,运行起来,浏览器就累得够呛,开发也够呛,使用代码来创建界面绝对是个糟糕的方式,Javascript的弱语言类型使得Ext开发就像行走在雷区,减少bug的唯一方法就是不要写出bug,一旦出现bug,调试将是一件极为痛苦的事情 !在几千行代码里跟踪、跳转真让人抓狂!

Javascript做面向对象开发的时候,总是会用到很多模拟面向对象特性的方法,这些方法就构成了支撑面向对象Javascript的核心代码,以下就是部分代码,其中参考了很多JQuery与Ext的核心代码,用来学习还不错,也可以做一些小的开发!

/*
功能:核心脚本方法
作者:LQB
2008-12-22
*/
var JCore = {//构造核心对象
    version:1.0,
    $import:function(importFile){
        var file = importFile.toString();
        var IsRelativePath = (file.indexOf("$")==0 ||file.indexOf("/")==-1);//相对路径(相对于JCore)
        var path=file;
        if(IsRelativePath){//计算路径
            if(file.indexOf("$")==0)
                file = file.substr(1);
            path = JCore.$dir+file;
        }
        var newElement=null,i=0;
        var ext = path.substr(path.lastIndexOf(".")+1);
        if(ext.toLowerCase()=="js"){
            var scriptTags = document.getElementsByTagName("script");
            for(var i=0;ilength;i++) {  
                if(scriptTags[i].src && scriptTags[i].src.indexOf(path)!=-1)
                    return;
            }
            newElement=document.createElement("script");
            newElement.type="text/javascript";
            newElement.src=path;
        }
        else if(ext.toLowerCase()=="css"){
            var linkTags = document.getElementsByTagName("link");
            for(var i=0;ilength;i++) {
                if(linkTags[i].href && linkTags[i].href.indexOf(path)!=-1)
                    return;
            }
            newElement=document.createElement("link");
            newElement.type="text/css";
            newElement.rel="Stylesheet";
            newElement.href=path;
        }
        else
            return;
        var head=document.getElementsByTagName("head")[0];
        head.appendChild(newElement);
    },
    $dir : function(){
            var scriptTags = document.getElementsByTagName("script");
            for(var i=0;ilength;i++) {  
                if(scriptTags[i].src && scriptTags[i].src.match(/JCore/.js$/)) {  
                    path = scriptTags[i].src.replace(/JCore/.js$/,"");   
                    return path;
                }
            }
            return "";
    }(),
    $ : function(element){
            return (typeof(element) == 'object' ? element : document.getElementById(element));
        },
    browser : {
        isFirefox:navigator.userAgent.toLowerCase().indexOf ('gecko') != -1,
        isChrome:navigator.userAgent.toLowerCase().indexOf ('chrome') != -1,
        isOpera:navigator.userAgent.toLowerCase().indexOf ('opera') != -1,
        isIE:navigator.userAgent.toLowerCase().indexOf ('msie') != -1,
        isIE7:navigator.userAgent.toLowerCase().indexOf ('7.0') != -1
    },
    onReady: function(newFunction){
        if(typeof(newFunction) == 'undefined')
            return false;
        this.domReady = false;
        if(typeof(functions) == 'undefined')
            var functions = [];
        functions.push(newFunction);
        var initial = function(){//执行事件列表
            for(var i=0; i< functions.length;i++){
                functions[i]();
            }
        }
        this.ready = function(){//加载事件
            if(this.domReady)
                initial();
            var Browser = JCore.browser;    
            if (Browser.isFirefox || Browser.isOpera || Browser.isChrome) {//FX
                try {
                    document.removeEventListener('DOMContentLoaded', initial);
                }catch(e){}
                document.addEventListener('DOMContentLoaded', initial, false);
                this.domReady = true;
            }
            else if (Browser.isIE) {//IE
                var timer = window.setInterval(function(){
                    try {
                        var IsReady = false;
                        document.body.doScroll("left");
                        IsReady=true;
                        initial();
                        window.clearInterval(timer);
                        this.domReady = true;
                    } 
                    catch (e){
                        if(IsReady){//文档加载已经完毕,抛出异常说明是调用的方法出错
                            var ErrorMsg = "onReady的方法中发生错误!/r/n";
                                ErrorMsg+="错误信息:"+e.message+"/r/n";
                                ErrorMsg+="错误描述:"+e.description+"/r/n";
                                ErrorMsg+="错误类型:"+e.name+"/r/n";
                                alert(ErrorMsg);
                                window.clearInterval(timer);
                        }
                    }
                }
                , 5);    
            }
        }
        this.ready();
    },
    apply:function(oDes, oSrc,bReplace){//为对象拷贝其它对象的属性,bReplace可选
        if(oDes && oSrc && typeof(oSrc) == 'object'){
            for(var p in oSrc){
                if(bReplace == false && oDes[p] != null) { continue; }
                oDes[p] = oSrc[p];
            }
        }
        return oDes;
    },
    override : function(origclass, overrides){//为类增加重载方法,eg:override(function class(){},{A:function(){},B:function(){}});
            if(overrides){
                var p = origclass.prototype;
                for(var method in overrides){
                    p[method] = overrides[method];
                }
            }
        },
    extend  :function(){
            // inline overrides
            var inlineOverride = function(o){
                for (var m in o) {
                    this[m] = o[m];
                }
            };
            /*需要实现重载的基类方法需要在父类prototype中定义;
            * 在子类中方法的可见度:子类构造中的属性>父类构造中的属性>子类prototype定义的属性==overrides>父类prototype定义的属性
            * 由于overrides方法被附加到子类的prototype中,所以:子类prototype定义的属性与overrides,两者后定义的可见
            * extend方法将重写子类的prototype,因此在子类的prototype上定义属性则必须在extend()方法调用之后再定义才有效
            * 对于一个类:构造中定义的属性>prototype定义的属性
            *
            *类派生的准则:
            *   1.建议把基类中可重写的方法定义在基类prototype中
            *   2.如果在派生类的prototype中定义属性方法,必须在extend()方法之后
            *   3.在派生类的构造中调用基类的构造:
            *       if(Sub.superclass) //sub即子类的名称
            *           Sub.superclass.constructor.call(this, Args);//Args即父类的构造方法的参数
            *   4.注意数组的浅拷贝问题
            *示例:
            *   var ClassA=function(){this.Show=function(){alert("Hello World!");}};
            *   var ClassB=function(){};
            *   JCore.extend(ClassB,ClassA);
            *   var ObjectB = new ClassB();
            *   ObjectB.Show();
            */
            return function(subFn, superFn, overrides){//子类,父类,重载方法(可选)
                var F = function(){}, subFnPrototype, superFnPrototype = superFn.prototype;
                F.prototype = superFnPrototype;
                subFnPrototype = subFn.prototype = new F();
                subFnPrototype.constructor = subFn;
                subFn.superclass = superFnPrototype;//父类
                if (superFnPrototype.constructor == Object.prototype.constructor) {
                    superFnPrototype.constructor = superFn;
                }
                subFn.override = function(obj){//override
                    JCore.override(subFn, obj);
                };
                subFnPrototype.override = inlineOverride;
                if(overrides)
                    JCore.override(subFn, overrides);
                return subFn;
            };
    }(),//括号不可少,表示调用内部返回的方法
    namespace : function(ns){//eg: JCore.namespace("JCore", "JCore.util");
            var args=arguments, o=null, i, j, d, rt;
            for (i=0; ilength; ++i) {//遍历参数
                d=args[i].split(".");//遍历点分隔符
                rt = d[0];
                eval('if (typeof ' + rt + ' == "undefined"){' + rt + ' = {};} o = ' + rt + ';');
                for (j=1; jlength; ++j) {
                    o[d[j]]=o[d[j]] || {};
                    o=o[d[j]];
                }
            }
    },
    isEmpty : function(value){
            return value === null || typeof(value) === 'undefined' || value === '';
        },
    idSeed : 0,
    id : function(el, prefix){
            prefix = prefix || "JCore-gen";
            el = this.$(el);
            var id = prefix + (this.idSeed++);
            return el ? (el.id ? el.id : (el.id = id)) : id;
        }
};
/*--------------------------------------------Function对象扩展-------------------------------------------*/
var FunctionExtendMethod ={
    createCallback : function(/*args...*/){//此参数即创造者的参数
        /*示例:function func1(arg1,arg2){alert(arg1+arg2);}
         *      var myfunc = func1.createCallback(1,2);
         *      myfunc();//即调用了func1
        **/
        var args = arguments;
        var method = this;
        return function(/*args...*/) {//如果在调用时传了参数,则创建时传的参数无效
            var callArgs = arguments.length>0 ? arguments : args;
            return method.apply(window, callArgs);
        };
    },
    createDelegate : function(argsArray,scope){//参数可选
        //参数一个数组,与createCallback区别:createCallback参数是可变参数,createDelegate的argsArray参数必须是数组
        var method = this;
        return function(/*args...*/) {//如果在调用时传了参数,则创建时传的参数无效
            var callArgs = typeof(argsArray)=="undefined"?[]:argsArray;
            callArgs = arguments.length>0 ? arguments : callArgs;
            return method.apply(scope||window, callArgs);
        };
    },
    defer : function(millis/*,args...*/){//参数:延迟时间(毫秒),可选参数列表
        /*示例:function func1(arg1,arg2){alert(arg1+arg2);}
         *      func1.defer(1000,1,2);//延迟1秒调用了func1(1,2)
        **/
        var callArgs = Array.prototype.slice.call(arguments, 1);
        var fn = this.createDelegate(callArgs);
        if(millis){
            return setTimeout(fn, millis);
        }
        fn();
        return 0;
    },
    createInterceptor : function(fcn, scope){
        if(typeof fcn != "function"){
            return this;
        }
        var method = this;
        return function() {
            fcn.target = this;
            fcn.method = method;
            if(fcn.apply(scope || this || window, arguments) === false){
                return;
            }
            return method.apply(this || window, arguments);
        };
    }
 };
 JCore.apply(Function.prototype,FunctionExtendMethod);
 /*--------------------------------------------String对象扩展----------------------------------------*/
 var StringExtendMethod ={
        trim : function(){//去掉首尾空格
            return this.replace(/(^/s*)|(/s*$)/g,"");//将字符串前后空格,用空字符串替代。
        },
        replaceAll : function (AFindText,ARepText){//替换所有,replace只替换第一个
                        raRegExp = new RegExp(AFindText,"g");
                        return this.replace(raRegExp,ARepText);
        },
        htmlEncode : function(){//编码HTML和解码Html。过滤掉双引号,单引号,符号&,符号<,符号
            return this.replace(/&/g,"&").replace(/<").replace(/>/g,">").replace(//"/g,""").replace(//'/g,"'");
        },
        htmlDecode : function(){
            return this.replace(//&/;/g, '/&').replace(//>/;/g, '/>').replace(//</;/g, '/<').replace(//"/;/g, '/'').replace(//&/#39/;/g, '/'');
        },
        format : function(){
            var args=arguments;
            return this.replace(//{(/d+)/}/g, function(m, i){
                    return args[i];
            });
        },
        convertWarpSymbol : function(){
            var reg1,reg2,reg3;
            if(this.toLowerCase().indexOf("")!=-1){
                reg1  = / /gi; reg2 = //gi;
                return this.replace(reg1," ").replace(reg2,"/r/n");
            }
            else{
                reg1  = / /g;reg2 = //r/n/gi;
                return this.replace(reg1," ").replace(reg2,"
");
            }
        },
        IsNum : function(){
            var reg = /^/d+$/g;
            return reg.test(this);
        }
 };
 JCore.apply(String.prototype,StringExtendMethod);
 JCore.apply(String,{//静态方法
                trim : function(str){//去掉首尾空格
                        return str.replace(/(^/s*)|(/s*$)/g,"");//将字符串前后空格,用空字符串替代。
                    }
            });
  /*--------------------------------------------Array对象扩展----------------------------------------*/
  var ArrayExtendMethod ={//去掉数组中重复的元素
            strip : function(){
                if(this.length<2) return [this[0]]||[];
                var arr=[];
                for(var i=0;i<this.length;i++){
                    var repeat=false;
                    for(var j=0;jlength;j++){
                        if(this[i]===arr[j])
                            repeat=true;
                    }
                    if(!repeat)
                        arr.push(this[i]);
                }
                return arr;
            },
            exists : function(item){
                        for( var i = 0 ; i < this.length ; i++ ){
                            if( item === this[i])
                                return true;
                        }
                        return false;
            },
            indexOf : function(item){
                for (var i = 0; i < this.length; i++){
                     if(this[i] === item) return i;
                }
                 return -1;
            },
            remove : function(item){
                var index = this.indexOf(item);
                if(index != -1){
                    this.splice(index, 1);
                }
                return this;
            }
  };
  JCore.apply(Array.prototype,ArrayExtendMethod);
/*--------------------------------------------Date对象扩展----------------------------------------*/
  var DateExtendMethod ={//返回时间间隔(毫秒)
        getElapsed : function(date) {
            return Math.abs((date || new Date()).getTime()-this.getTime());
        }
  };
  JCore.apply(Date.prototype,DateExtendMethod);

原发布于面向对象Javascript核心支持代码(2009-05-13 21:31),现转于此!