`
绿窗明月
  • 浏览: 3513 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

我的js类

阅读更多

js类有很多中写法,网上也有很多现成的库,都有各自的优缺点,但用起来都不太顺手。所以总结改进后,写了自己的类,只图用起来顺手,看起来顺眼。

比较喜欢mootools,语法和它类似。initialize为构造方法,statics为静态属性及方法,superclass为父类;在当前方法中调用父类方法使用this.callSuper(),在当前方法中调用父类的其它方法this.invokeSuper('methodName').execute(args);

js中类的写法有一个痛点,即没法完全实现私有属性方法、受保护属性方法。mootools中有相关的内容,但也只是在继承的层面上实现部分功能,并不能控制一个对象外部对私有方法、受保护方法的访问。

使用方法如下:

 

Class('myclass.A',{
	initialize:function(){
		this.name='A';
	},
	showName:function(){
		alert(this.name);
	}	
});
Class('myclass.B',{
	superclass:myclass.A,
	initialize:function(){
		this.name='B';
	},
	showSuperName:function(){
		this.invokeSuper('showName').execute();
	},
	showName:function(){
		alert('<<<')
		this.callSuper();
		alert('>>>')
	}	
});
var a=new myclass.A();
a.showName();
var b=new myclass.B();
b.showName();
var b=new myclass.B();
b.showSuperName();


源码如下,仍需完善,仅供大家参考。

 

(function () {
    var noArgs = [],
        emptyFn = function () {
        },
        noInvokeResult = {
            execute: emptyFn
        },
        invokeSuperResult = {
            execute: function () {
                var result = this.method.apply(this.obj, arguments || noArgs);
                this.obj = null;
                this.method = null;
                return result;
            }
        },
        enumerables = ['hasOwnProperty', 'valueOf', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'constructor'];

    function namespace() { // namespace
        var a = arguments,
            o = null,
            i,
            j,
            d,
            rt;
        for (i = 0; i < a.length; ++i) {
            d = a[i].split(".");
            rt = d[0];
            eval('if (typeof ' + rt + ' == "undefined"){' + rt + ' = {};} o = ' + rt + ';');
            for (j = 1; j < d.length; ++j) {
                o[d[j]] = o[d[j]] || {};
                o = o[d[j]];
            }
        }
        return o;
    }

    function inherit(C, superClass) {
        if (typeof(superClass) != 'function') {
            return C;
        }
        function F() {}
        F.prototype = superClass.prototype;
        C.prototype = new F();
        C.prototype.constructor = C;
        C.superclass = superClass;
        return C;
    }
    function addMethods(C, methods) {
        var p = C.prototype;
        for (var name in methods) {
            var m = methods[name];
            m['_name_'] = name;
            m['_owner_'] = C;
            p[name] = m;
        }
        return C;
    }

    //TODO 1、需增加获取静态属性、方法的方法2、增加获取祖先的方法ancestor
    function callSuper() {
        var method = arguments.callee.caller,
            superMethod;
        if (method) {
            if (method._owner_) {
                superMethod = method._owner_.superclass.prototype[method._name_];
            } else if (method.superclass) {
                superMethod = method.superclass;
            } else {
                superMethod = emptyFn;
            }
            return superMethod.apply(this, arguments || noArgs);
        }
    }

    var staticUtil = {
        getStatic: function (name) {
            return this.constructor[name];
        }
    };

    var invokeSuper = (function () {
        var obj, superMethod,
            proxyResult = {
                execute: function () {
                    var result = superMethod.apply(obj, arguments || noArgs);
                    obj = null;
                    superMethod = null;
                    return result;
                }
            };

        function proxy(name) {
            try {
                superMethod = proxy.caller._owner_.superclass.prototype[name];
                if (!superMethod) {
                    throw(0);
                }
                obj = this;
                return proxyResult;
            } catch (e) {
                throw(new Error("[invokeSuper error]: the method " + name + "'s super is not exist!"));
            }
        }

        return proxy;
    })();

    function Class() {
        var options,
            initialize,
            superclass,
            statics,
            mixin,
            fullName,
            className,
            path;
        if (arguments.length == 1) {
            options = arguments[0];
        } else if (arguments.length == 2) {
            fullName = arguments[0];
            path = fullName.split(".");
            className = path.pop();
            if (path.length > 0) {
                path = namespace(path.join('.'));
            } else {
                path = window;
            }
            options = arguments[1];
        } else {
            fullName = "";
            className = "";
        }
        if ('initialize' in options) {
            initialize = options['initialize'];
            delete options['initialize'];
        } else {
            initialize = function () {
            };
        }
        // TODO火狐中name属性无法赋值
        if (options.hasOwnProperty('statics')) {
            statics = options['statics'];
            for (var k in statics) {
                if (statics.hasOwnProperty(k)) {
                    initialize[k] = statics[k];
                }
            }
            delete options['statics'];
            addMethods(initialize, staticUtil);
        }
        if ('superclass' in options) {
            superclass = options['superclass'];
            if (superclass) {
                inherit(initialize, superclass);
                superclass.prototype.callSuper || addMethods(initialize, {
                    callSuper: callSuper,
                    invokeSuper: invokeSuper
                });
                delete options['superclass'];
            } else {
                throw TypeError("the superclass of '" + fullName + "' is undefined!");
            }
        }
        addMethods(initialize, options);
        if (options.hasOwnProperty('mixin')) {
            mixin = options['mixin'];
            if(mixin.length&&mixin.pop){
                for(var i=0;mixin[i]!=undefined;i++){
                    addMethods(initialize,mixin[i]);
                }
            }else{
                addMethods(initialize,mixin);
            }
            delete options['mixin'];
        }
        if (className) {
            path[className] = initialize;
            path = arguments[0];
        }
        initialize._isClass_ = true;
        initialize._name_ = className;
        initialize._fullName_ = fullName;
        return initialize;
    }
    window.Class = Class;
})();



分享到:
评论

相关推荐

    JS(javascript)-md5加密工具类

    JavaScript中的MD5加密工具类是用于对数据进行安全哈希的一种方法,广泛应用于密码存储、数据完整性校验等场景。MD5(Message-Digest Algorithm 5)是一种广泛使用的哈希函数,它能将任意长度的输入转化为固定长度的...

    javascript 原生态js类继承实现的方式

    类定义了一类事物公共的行为和方法;而实例则是类的一个具体实现。 我们还知道,面向对象编程有三个重要的概念 - 封装、继承和多态。 但是在JavaScript的世界中,所有的这一切特性似乎都不存在。 因为JavaScript...

    javascript后台调用的工具类

    JavaScript(JS)是一种广泛应用于客户端和服务器端的脚本语言,尤其在Web开发中占据着重要地位。其语法简洁,学习曲线相对平缓,使得它成为开发者的首选工具之一。 "javascript.cs" 这个文件名暗示了这是一个用C#...

    javascript div弹出窗口 可封装为JS类

    在本案例中,"可封装为JS类"意味着开发者创建了一个可复用的JavaScript对象,该对象可以方便地管理和控制这些弹出窗口。 首先,让我们了解`div`元素。在HTML中,`&lt;div&gt;`是“division”(分隔)的缩写,是一个通用的...

    一个JS类(收藏)

    2. **类与实例**:在JavaScript中,类的概念相对较弱,但Prototype.js引入了`Class.create`函数,允许我们创建类的实例,模拟传统的面向对象编程中的类。 3. **函数委托**:Prototype.js通过`Prototype.Browser`来...

    C#的一个JS类 (方便)

    C#的一个JS类C#的一个JS类C#的一个JS类C#的一个JS类C#的一个JS类C#的一个JS类C#的一个JS类

    javascript写类方式之六

    尽管没有具体的代码,但可以想象它可能包含了一个使用上述类方式实现的JavaScript类。通过分析这个文件,我们可以学习到实际编程中类的运用,以及如何将理论知识应用到实践中。 总结起来,JavaScript的类方式多种...

    自定义JS类框架

    "自定义JS类框架"指的是开发者根据自身需求,利用JavaScript语言特性(如原型链、闭包、模块化等)和jQuery库,构建的一种自定义的框架。这个框架可能是为了简化DOM操作、提供更高级别的API、优化性能或者实现特定的...

    通用不间断滚动JS封装类

    在这个场景下,"通用不间断滚动JS封装类"可能是一个自定义的JavaScript类,它包含了实现滚动效果所需的所有方法和属性。 描述中提到的博文链接(https://aina5626.iteye.com/blog/1201724)是深入理解这个封装类的...

    c#语言Asp.net好用的JS脚步类JavaScript。

    在文件名“Asp.net好用的JS脚步类”中,我们可以推测这可能是一个包含实用JavaScript函数或类的集合,这些函数或类可能是为了解决ASP.NET开发中常见问题而设计的,比如表单验证、数据格式化、用户界面交互等。...

    asp.net中javascript通用类

    通过这样的通用JavaScript类,开发者可以创建出更健壮、可维护的ASP.NET应用,同时提高开发效率。不过,随着技术的发展,现代Web开发中更多地倾向于使用库和框架(如jQuery、React、Vue等),它们提供了更高级别的...

    javascript表单验证类

    基于jquery的form表单验证类,工程项目为.net项目,主要是做了详细的调用例子,如果不使用.net,可以直接formvaildator-1.0.js或formvaildator-1.0.min.js,里面也有详细的调用说明,不过项目说明因为有例子会直观...

    新手常用的几个JS封装类

    在JavaScript编程中,封装是面向对象编程的一个重要概念,它有助于提高代码的可...在压缩包文件“常用的js类”中,可能包含了这些功能的具体实现,新手可以通过学习和理解这些代码,进一步提升自己的JavaScript技能。

    封装js工具类

    根据提供的文件信息,我们可以看到这是一个用于封装JavaScript功能的C#类。下面将详细介绍该类中的各个方法及其用途。 ### 封装JS工具类 #### 1. Echo 方法 该方法的功能是向客户端输出指定的消息。 ```csharp ...

    省、市、地区联动选择JS封装类.

    标题中的“省、市、地区联动选择JS封装类”指的是一个JavaScript编程实现的功能,它用于在网页中创建一个联动选择的下拉菜单,通常用于用户输入他们的省份、城市和区域信息。这种联动选择框能够根据用户选择的省份...

    公历与农历互转的js类

    在IT行业中,编程语言JavaScript(js)是一种广泛使用的脚本语言,尤其在Web开发领域,无论是前端还是后端都有其身影。在这个场景中,我们关注的是一个名为"公历与农历互转的js类"的工具,它适用于微信小程序以及H5...

    javascript中类和继承(代码示例+prototype.js)

    本文将深入探讨JavaScript中的类和继承,并结合`prototype.js`文件中的示例进行解析。 ### 类的概念与模拟 在JavaScript中,我们通常使用函数来模拟类的行为。一个函数可以看作是一个类的定义,通过`new`关键字来...

    js定义类 对象 构造函数,类的继承

    在提供的`ClassDefineAndExtends.js`文件中,可能包含了关于类定义和继承的示例代码。通过分析这个文件,我们可以看到实际应用中的类定义和继承实践,包括如何定义类,如何使用构造函数初始化对象,以及如何通过`...

    js酒店价格日历_js门票价格日历_javascript价格日历

    此程序是javascript和php开发,提供酒店、门票订购... 此程序中js是驴妈妈上的,我做了些修改,做学习用,精简了代码和功能,只提供酒店和门票,部分提交url请自己修改。php生成日历的类是自己原创的。不足之处请反馈。

Global site tag (gtag.js) - Google Analytics