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

我的js类(续)

阅读更多

之前的写过一篇关于js类的《文章》,主要是贴了一下代码和用法,功能上也有些欠缺。新版的Class增加了私有属性、接口两个功能。需要注意的是继承、调用父类方法、使用私有方法都是很耗费资源的,如果非得使用尽量减少继承的层数。(本人的小demo大笑

主要贴一下私有属性和接口用法:

1、私有属性

 

//设置私有属性this.$(key,value);获取私有属性:this.$(key);
Class('Dog',{
	initialize:function(){
		//为Dog设置私有属性name
		this.$('name','dog');
	},
	speak:function(){		
		//打印Dog私有属性name
		console.log('Dog name is ',this.$('name'));
	}
	
})
Class('BlackDog',{
	superclass:Dog,
	initialize:function(){
		this.callSuper();
		//为BlackDog也设置私有属性name,检查子类和父类里的私有属性是否冲突
		this.$('name','blackdog');
	},
	speak:function(){
		this.callSuper();
		//打印BlackDog私有属性name
		console.log('BlackDog name is ',this.$('name'));
	}
})
//正确结果应该Dog里的name和BlackDog里的name没有关系,BlackDog不能覆盖Dog里的私有属性
var blackdog=new BlackDog();
blackdog.speak();

结果为:

 

Dog name is dog
BlackDog name is blackdog


2、接口

 

Interface('Animal',['eat']);//接口名称、方法
Class('Pig',{
	interfaces:[Animal]
})
Interface('Animal',['eat']);//接口名称、方法
Class('Cat',{
	interfaces:[Animal],
	eat:function(){
		
	}
})

结果为:

报错:Error: the method 'eat' need to implement in class 'Pig'!

 

下边是新版的源码:

 

(function () {
    var emptyArgs = [],
        emptyFn = function () {
        },
    //暂时未用
        noInvokeResult = {
            execute: emptyFn
        },
    //暂时未用
        invokeSuperResult = {
            execute: function () {
                var result = this.method.apply(this.obj, arguments || emptyArgs);
                this.obj = null;
                this.method = null;
                return result;
            }
        },
    //暂时未用
        enumerables = ['hasOwnProperty', 'valueOf', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'constructor'];
    //命名空间
    function namespace() { // namespace
        var a = arguments,
            al = a.length,
            o = null,
            i,
            j,
            d,
            dl,
            rt;
        for (i = 0; i < al; ++i) {
            d = a[i].split(".");
            rt = d[0];
            eval('if (typeof ' + rt + ' == "undefined"){' + rt + ' = {};} o = ' + rt + ';');
            dl = d.length;
            for (j = 1; j < dl; ++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 bindMethods(object, methods) {
        for (var name in methods) {
            if (methods.hasOwnProperty(name)) {
                object[name] = methods[name];
            }
        }
    }

    //添加方法到原型
    function addMethods(C, methods) {
        var p = C.prototype,
            _methods_ = C._methods_;
        for (var name in methods) {
            var m = methods[name];
            p[name] = m;
            if (name != 'callSuper' && name != 'invokeSuper') {
                m['_name_'] = name;
                m['_owner_'] = C;
                if (_methods_.indexOf(name) == -1) {
                    _methods_.push(name);
                }
            }
        }
        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._wrapper_) {
                superMethod = method._wrapper_.superclass;
            } else {
                superMethod = emptyFn;
            }
            return superMethod.apply(this, arguments || emptyArgs);
        }
    }

    //暂时未用
    var staticUtil = {
        getStatic: function (name) {
            return this.constructor[name];
        }
    };

    //使用方法名调用父类方法
    var invokeSuper = (function () {
        var obj,
            superMethod,
            proxyResult = {
                execute: function () {
                    var result = superMethod.apply(obj, arguments || emptyArgs);
                    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 createPrivateClosure() {
        var privateProperties = {};
        return function (key, value) {
            if (value == undefined) {
                return privateProperties[key];
            } else {
                privateProperties[key] = value;
            }
        }
    }

    ////////////////////////////////////////////////////////////Class///////////////////////////////////////////////////////////
    //创建类
    function Class() {
        var clazz,
            options,
            initialize,
            interfaces,
            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 (options.hasOwnProperty('initialize')) {
            initialize = options['initialize'];
            delete options['initialize'];
        } else {
            initialize = function () {
            };
        }
        statics = options.hasOwnProperty('statics') ? options['statics'] : false;

        clazz = function () {
            var self = this,
            //私有属性的赋值、取值方法
                $ = function (key, value) {
                    var $method = arguments.callee,
                        caller = $method.caller,
                        callerClass = caller._owner_ || caller._wrapper_;
                    if (callerClass == $method._owner_) {
                        return $method.$$(key, value);
                    } else {
                        $method = $method._super_;
                        while ($method) {
                            if (callerClass == $method._owner_) {
                                break;
                            }
                            $method = $method._super_;
                        }
                    }
                    return $method.$$(key, value);
                };
            $.$$ = createPrivateClosure();
            $._owner_ = clazz;
            if (self.$) {
                $._super_ = self.$;
            }
            self.$ = $;

            //增加静态方法到实例本身
            statics && bindMethods(self, statics);
            initialize.apply(self, arguments);
        };
        initialize._wrapper_ = clazz;
        clazz._isClass_ = true;
        clazz._name_ = className;
        clazz._fullName_ = fullName;
        clazz._methods_ = [];
        clazz._interfaces_ = [];
        interfaces = options['interfaces'];
        mixin = options['mixin'];
        delete options['interfaces'];
        delete options['mixin'];

        //增加静态方法到类
        if (statics) {//TODO 火狐中name属性无法赋值
            for (var k in statics) {
                if (statics.hasOwnProperty(k)) {
                    clazz[k] = statics[k];
                }
            }
            delete options['statics'];
            addMethods(clazz, staticUtil);
        }

        //继承父类
        if (options.hasOwnProperty('superclass')) {
            superclass = options['superclass'];
            if (superclass) {
                inherit(clazz, superclass);
                superclass.prototype.callSuper || addMethods(clazz, {
                    callSuper: callSuper,
                    invokeSuper: invokeSuper
                });
                delete options['superclass'];
            } else {
                throw TypeError("the superclass of '" + fullName + "' is undefined!");
            }
        }

        //添加公有方法到类
        addMethods(clazz, options);

        //添加mixin方法到类
        if (mixin) {
            if (mixin.length && mixin.pop) {
                for (var i = 0; mixin[i] != undefined; i++) {
                    addMethods(clazz, mixin[i]);
                }
            } else {
                addMethods(clazz, mixin);
            }
            delete options['mixin'];
        }

        //实现、检查接口
        if (interfaces) {
            var _interfaces_ = clazz._interfaces_,
                _methods_ = clazz._methods_;
            if (!(interfaces instanceof Array)) {
                interfaces = [interfaces];
            }

            for (var i = 0, inter, methodName; interfaces[i] != undefined; i++) {
                inter = interfaces[i];
                for (var j = 0; inter[j] != undefined; j++) {
                    methodName = inter[j];
                    if (_methods_.indexOf(methodName) == -1) {
                        throw new Error("the method '" + methodName + "' need to implement in class '" + fullName + "'!");
                    }
                }
                _interfaces_.push(inter);

            }
        }
        if (className) {
            path[className] = clazz;
            path = arguments[0];
        }
        return clazz;
    }

    window.Class = Class;
    //命名空间
    Class.ns = namespace;
    //根据路径获取类
    Class.get = function (source) {
        try {
            var path = source.split('.'),
                obj = window[path[0]];
            if (path.length > 1) {
                for (var i = 1; path[i] != undefined; i++) {
                    obj = obj[path[i]];
                }
            }
            return obj;
        } catch (e) {
            throw new TypeError("no such class '" + source + "' is defined!");
        }
    };
    //为类设置别名
    Class.alias = function (source, alias) {
        var clazz,
            path = alias.split('.'),
            aliasName = path.pop(),
            aliasPath = path.join('.');
        if (typeof source == 'string') {
            clazz = Class.get(source);
        } else if (source._isClass_) {
            clazz = source;
        }
        if (clazz) {
            if (aliasPath) {
                namespace(aliasPath);
                Class.get(aliasPath)[aliasName] = clazz;
            } else {
                window[aliasName] = clazz;
            }
        }
    };
    ////////////////////////////////////////////////////////////Interface///////////////////////////////////////////////////////////
    function _interface(fullName, methods) {
        this.fullName = fullName;
        for (var i = 0; methods[i] != undefined; i++) {
            this[i] = methods[i]
        }
    }

    function Interface(fullName, methods) {
        if (methods instanceof Array) {
            var path = fullName.split("."),
                className = path.pop();
            if (path.length > 0) {
                path = namespace(path.join('.'));
            } else {
                path = window;
            }
            path[className] = new _interface(fullName, methods);
        } else {
            throw new Error("Interface '" + fullName + "' second must be Array!");
        }
    }

    window.Interface = Interface;
})();

代码还需改进,努力中奋斗

分享到:
评论

相关推荐

    plupload断点续传

    综上所述,Plupload的断点续传功能通过Moxie.js对文件进行分块,然后利用plupload.js的API实现上传和续传操作。开发者可以通过`GboatFileUploadInterceptor.java`这样的后台逻辑来配合前端的Plupload,确保整个上传...

    如何编写高质量JS代码(续)

    继续上一篇文章《如何编写高质量JS代码》今次整理一下javascript函数知识点。 2.使用函数 函数给程序员提供了主要的抽象功能,又提供实现机制。函数可以独立实现其他语言中的多个不同的特性,例如,过程、方法、构造...

    Javascript 类与静态类的实现(续)

    在JavaScript中,类和静态类的概念对于理解和编写可维护、模块化的代码至关重要。JavaScript是一种动态类型的语言,不支持像Java或C#那样的传统类结构,但它可以通过模拟来实现类的概念。在JavaScript中,我们可以...

    MinIo最佳性能分片上传、断点续传方案

    在提供的"类vue-simple-uploader+minio分片上传"压缩包中,可能包含以下内容: 1. `vue-simple-uploader`前端组件的配置和使用示例,展示如何设置分片大小、并发数以及如何处理断点续传。 2. MinIO的后端接口实现,...

    jquery-大文件上传插件,支持分片上传,断点续传

    jQuery,作为一个广泛使用的JavaScript库,提供了一系列的插件来解决这个问题。"jquery-大文件上传插件,支持分片上传,断点续传"就是这样一个解决方案,它针对大文件上传进行了优化,确保了高效且用户友好的体验。 ...

    基于Java的的文件图片上传-分片上传-断点续传-秒传java源码.zip

    4.图片上传部分:在文件上传部分已有功能的基础上实现了上传前缩略图预览,前台js文件后缀验证,后台代码文件后缀验证和文件类型验证(就算修改后缀名也无法成功上传),支持图片上传前压缩; 5.多选择器多文件上传...

    SWF 断点续传Java、PHP、Perl

    在“压缩包子文件的文件名称列表”中只给出了“stream”,这可能是一个文件或目录名,它可能包含了实现断点续传功能的核心代码,比如流处理类或函数,因为“stream”在编程中通常指数据流,尤其是处理大文件时,会...

    flex+socket实现断点续传(上传文件)源码

    `swfobject.js` 是一个JavaScript库,用于检测和嵌入SWF文件到HTML页面中,确保在不同浏览器上的兼容性。 **Socket通信** 是在网络编程中常用的一种技术,它允许客户端和服务器之间建立双向通信通道。在本项目中,...

    Android JSON 断点续传

    在Android开发中,JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,常用于服务器与客户端之间的数据传输。在本场景中,“Android JSON 断点续传”指的是利用JSON数据来控制Android应用进行文件下载...

    完整版断点续传、秒传,支持超大大大文件_支持重定义文件名和路径

    断点续传和秒传功能需要通过特定的JavaScript库或者Flash插件来实现对IE8的支持,因为这些老版本的浏览器可能无法原生处理这样的高级网络操作。开发者通常需要编写兼容代码,确保在这些旧浏览器上也能正常运行,从而...

    java+vue断点续传核心代码

    - `js`:前端的JavaScript代码,实现Vue.js应用的逻辑,包括文件选择、分块、上传和断点续传功能。 - `dto`:数据传输对象(Data Transfer Object),在Java和Vue.js之间交换数据的模型类。 通过这些核心代码,我们...

    air 断续续传

    在IT行业中,断点续传是一项非常实用的技术,特别是在大文件传输时,它能有效解决网络中断或传输错误的问题。本项目聚焦于Adobe AIR平台,它是一个跨平台的应用开发框架,允许开发者创建桌面应用程序,利用Flash ...

    springboot整合plupload,实现文件批量上传、断点续传、秒传 源码

    在SpringBoot中,我们需要创建一个存储这些信息的模型类和数据库表,并在接收到文件块后更新状态。 秒传是通过比较服务器上已存在的文件MD5值,如果匹配,就直接返回已存在文件的URL,而不需要再次上传。这个功能...

    大文件上传 webuploader插件 进度条 断点续传

    - `fileUploadUtil.js`: JavaScript工具类,可能包含了WebUploader的初始化、事件绑定、参数设置等实用函数。 - `0.1.5`: 这可能是WebUploader的版本号,表示所使用的插件为0.1.5版本。 在实际应用中,开发者需要...

    断点续传。

    结合标题和描述,这个项目可能包含一个Android应用,该应用利用JavaScript或者原生Android API实现了一个断点续传功能,可能在WebView中加载网页资源,或者通过Android的DownloadManager服务下载文件。开发者可能在...

    java实现大文件上传分片上传断点续传.zip

    这通常涉及JavaScript的`FileReader` API,通过`slice()`方法切割文件,然后使用`XMLHttpRequest`或`fetch`进行异步请求。 7. **错误处理和重试机制**:为了保证文件上传的可靠性,需要有完善的错误处理机制,如...

    断点续传123

    - **JavaScript(浏览器环境)**:使用`fetch` API,可以在请求选项中设置`headers: {'Range': 'bytes=' + offset + '-'}`。 4. **网络MP3播放与断点续传** 在网络MP3播放中,断点续传同样发挥着重要作用。音频流...

    C# 常用类代码(封装)

    7.js.cs 常用js代码 8.文件操作类 9.数据检查类 10.util.cs常用字符串操作 11.CacheManager.cs 操作缓存的类 12.CookieManager.cs Cookie管理类 13.DataToExcel.cs 导出excel 14.EnumConvert 枚举转换为详细说明的类...

    Node.js-node.js七牛云文件上传

    在本文中,我们将深入探讨如何使用Node.js与七牛云进行...同时,为了提高用户体验,可以考虑采用断点续传和多线程上传等高级特性。对于大型项目,建议将七牛云的相关操作封装成服务或者模块,方便在整个项目中复用。

Global site tag (gtag.js) - Google Analytics