欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Javascript - 类的封装 JavaScriptjsonprototypeclassoo 

程序员文章站 2022-07-14 13:09:45
...
类的封装 要干的事情如下


实际上就是一个function
同时也是这个类的构造方法
可以使用new创建该类的实例
new出的对象 有属性 有方法

属性和方法性质不同 因此定义的方式也不同
——实际上方法是一种特殊形式的属性

属性
每个实例单独所有 多个实例之间互不影响
因此要在构造方法中初始化实例的属性
——每次执行new时构造方法都会执行 会产生新的属性
——在其中定义方法当然也会 但不推荐 耗内存

方法
所有实例共有 创建多个实例不会产生新的function
因此要在类的prototype中定义实例的方法
——prototype中的方法会被所有实例共有
——在其中定义属性当然也会 但不推荐 除非你知道自己在做什么

至于private 算了吧
Javascript里没private 硬要实现的话虽然也能 但是有点不伦不类
按照惯例 在属性或方法名前加一个下划线 声明为私有
外面看见这个不要动 假装没看见就好了

至于static 这个容易
var Class = function() {};
Class.field = "";
Class.method = function() {};
没必要多说

单例
更不用费什么劲了
var Singleton = {
    field: "",
    method: function() {
    }
};

命名空间 这个很有必要 尤其是在复杂的应用中
不过现在这个不是重点 日后详谈

原则
简单
高效
Javascript就是Javascript而不是别的什么
——不要觉得Java或其它语言有什么Javascript就该有什么
或许使用各种变态的方式可以实现 但很别扭 更不优雅

终于 到了 正题

偶然看见了 alzui类封装的演化过程
以前也曾经干过类似的事情 但是用了好多代码
就没想过这件事情可以这么简单
仔细的研究了代码 佩服得不得了
不过貌似演化的最终结果有冗余的代码
实在没办法理解是否作者更深远的意图
在原文下提了 暂时还没得到作者的回复

下面是按照个人想法对作者最终版本的简化
貌似 挺好 没有问题
function _class(className, classImp){  
    var clazz = function(){  
        this._init.apply(this, arguments);  
    };  
    window[className] = clazz;  
    classImp.apply(clazz.prototype);  
}


其实演化还可以继续的

1. 干掉了那个傀儡 并改用constructor
因为那个傀儡实际上也没什么用
而_init是Java的 而且是见不得人的
constructor 才是Javascript的
Javascript内置的所有的类的对象 都有constructor属性
指向类的本身 详见本文末尾测试代码
window.$Class = function(name, SRC) {
    var src = new SRC();
    window[name] = src.constructor;
    window[name].prototype = src;
};


定义类
// define Class
$Class("Guy", function() {
    this.constructor = function(name) {
        this.name = name;
        this.friends = [];
    };
    this.makeFriendWith = function(guy) {
        this.friends.push(guy.name);
    };
});


2. 再省掉一步 用JSON的格式定义类 更直观
或许这个可以叫做final版了 没办法再简单了
window.$Class = function(name, src) {
    src.constructor.prototype = src;
    window[name] = src.constructor;
};


定义类
$Class("Guy", {
    constructor: function(name) {
        this.name = name;
        this.friends = [];
    },
    makeFriendWith: function(guy) {
        this.friends.push(guy.name);
    }
});


测试
适用于以上两种方式
要用到JSON2
Firefox已内置 其它浏览器未知 sb-ie肯定没有
json2.js

测试代码
var minglq = new Guy("MingLQ");
var luoluo = new Guy("Luoluo");
minglq.makeFriendWith(luoluo);
luoluo.makeFriendWith(minglq);
var ____ = "--------------------------------";
alert([
    JSON.stringify(minglq),
    JSON.stringify(luoluo),
    ____,
    "minglq.friends !== luoluo.friends:\n    " + (minglq.friends !== luoluo.friends),
    "minglq.makeFriendWith === luoluo.makeFriendWith:\n    " + (minglq.makeFriendWith === luoluo.makeFriendWith),
    ____,
    "minglq instanceof Guy:\n    " + (minglq instanceof Guy),
    "luoluo.constructor === Guy:\n    " + (luoluo.constructor === Guy),
    ____,
    "Guy:\n" + Guy.toString()
].join("\n"));


测试结果
{"name":"MingLQ","friends":["Luoluo"]}
{"name":"Luoluo","friends":["MingLQ"]}
--------------------------------
minglq.friends !== luoluo.friends:
    true
minglq.makeFriendWith === luoluo.makeFriendWith:
    true
--------------------------------
minglq instanceof Guy:
    true
luoluo.constructor === Guy:
    true
--------------------------------
Guy:
function (name) {
    this.name = name;
    this.friends = [];
}


详见http://gist.github.com/iwill