6

By OO I mean classical OO. I keep going back and forth between defining my "classes" ( javascript does not have traditional classes ) using the module pattern to provide privacy and using object literals to create a collection of "public statics".

I have no guiding force when I create "classes" that lets me determine what type of organization to use. Well, besides the fact that my code passes both jshint and jslint w/ no options set.

I'm working w/ about 1500 lines of code so I need a "guiding force" before the code becomes un-manageable and I have to scrap it.

I am well aware of the different ways to write "classes" in JavaScript. Those taught by JavaScript Web Applications written by Alex MacCaw as well as the numerous ways listed here on SO.

However, application wise, I just don't know what method to use.

The simplest seems to be a collection of methods and variables in an object literal like this:

var public_statics = {
    public_func: function () {},
    public_var: "hello"
}

and the most complicated seems to be - an IIFE.

(function(){
    var private_var;
    function private_func(){
    }
})();

How do I know which one to use or the multitude of in-between variations?

For a concrete example: How about for a controller in the MVC.

Currently ( and some what randomly chosen), I implement a controller like this:

var Co = {};
Co.Controller = function(){
    // 'classes' from Mo are called here
    // 'classes' from Su are called here
}

then I tack on other Control related method to Co.

How do I choose what style of OO to use?


Updated

My library is currently divided between 4 namespaces:

var Mo = {},
    Vi = {},
    Co = {},
    Su = {};

Model, View, and Controller should be self-explanatory and (Su)pport is for all "classes" not contained in the MVC, for example DOM access, Effects, Debug code, etc.

What OO style should I use to further organize this library/code?

Controller "Class" example:

/**
 **  Controller
 */

Co.Controller = function (o_p) {
    var o_p_string_send;
    Su.time();
    o_p = Mo[o_p.model].pre(o_p);
    if (o_p.result !== 'complete') {
        o_p_string_send = JSON.stringify(o_p);
        Su.time();
        //Su.log(o_p_string_send);
        Co.serverCall('pipe=' + o_p_string_send, function (o_p_string_receive) {
            Su.time();
            //Su.log(o_p_string_receive);
            o_p.server = JSON.parse(o_p_string_receive);
            Mo[o_p.model].post(o_p);
            Su.time(true);
            Su.log('Server time: [' + o_p.server.time + ']');
        });
    }
};
4

3 回答 3

2

IFFEs 阅读起来常常令人困惑,就我个人而言,我不知道为什么它们变得如此主流。我认为代码应该易于阅读和简洁。试图模拟不属于语言规范的语言行为通常是一个非常愚蠢的想法。

例如,JavaScript 不支持多重继承、多态或许多其他有趣的范例。所以很多时候,我们看到人们试图在 JS 中创建这些具有多态性或私有成员等的疯狂方式。我认为这是一个错误。

我目前正在作为一种关于高性能 JS 数据结构库的爱好项目工作(我试图超越 Google 的关闭和其他一些)。来自 C++ 和 Java 背景,我总是喜欢制作东西类,我喜欢继承等。让我与你分享一些代码片段。起初,我认为我很聪明,因为我在写这样的东西:

function __namespace(n, v) {
    return {"meta":{"namespace":n,"version":v}};
}

var FJSL = FJSL == undefined ? new __namespace("Fast JavaScript Library", 0.1) : FJSL;

__using = function(parent, child) {
    clazz = new child();
    clazz.super = new parent();
    if (clazz.super == undefined) return clazz;
    for (a in clazz.super) {
        for (b in clazz) {
            if (a == "constructor" || b == "constructor") continue;
            if (clazz[b] === clazz.super[a]) continue;
            if (a == b && typeof clazz[b] != typeof clazz.super[a]) throw "Typesafety breached on '" + a + "' while trying to resolve polymorphic properties."; 
            if (a == b && typeof clazz[b] == typeof clazz.super[a]) {
                clazz["_"+a] = clazz.super[a];
            } else if (clazz[a] == undefined) {
                clazz[a] = clazz.super[a];
            }
        }
    }
    return clazz;
};

我就是这样使用它的(在一个简单队列的例子中):

FJSL.Array = function() { 
    this.data = [];

    this.contains = function(idx, element) {
        for (var i = idx; i < this.data.length; i++) {
            if (this.data[i] === element)
                return i;
        }
        return -1;
    }

    this.size = function() {
        return this.data.length;
    }
}

FJSL.Queue = function() {
    return __using(FJSL.Array, 
    function() {
        this.head = 0;
        this.tail = 0;

        this.enqueue = function(element) {
            this.data[this.tail++] = element;
        };

        this.dequeue = function() {
            if (this.tail == this.head)
                return undefined;
            return this.data[this.head++];
        };

        this.peek = function() {
            return this.data[this.head];
        };

        this.size = function() {
            return this.tail - this.head;
        };

        this.contains = function(element) {
            return this._contains(this.head, element);
        };
    }
)};

你会注意到我是如何伪装继承的(队列使用数组,哈哈,我很聪明)。但是,这对于a) 阅读b) 理解是绝对疯狂的。我不禁想起了这个模因:

在此处输入图像描述

让我向您展示功能等效的代码,而无需我尝试进行所有这些花哨的预处理和后处理:

FJSL.Queue = function(opts) {
    this.options = opts;
    this.head = 0;
    this.tail = 0;
    this.data = [];
};

FJSL.Queue.prototype = {
    add : function(element) {
        this.data[this.tail++] = element;
    },

    enqueue : function(element) {
        this.data[this.tail++] = element;
    },

    dequeue : function() {
        if (this.tail == this.head) {
            return undefined;
        }
        return this.data[this.head++];
    },

    peek : function() {
        return this.data[this.head];
    },

    size : function() {
        return this.tail - this.head;
    },

    contains : function(element) {
        // XXX: for some reason a for : loop doesn't get JIT'ed in Chrome
        for (var i = this.head; i < this.data.length; i++) {
            if (this.data[i] === element) {
                return true;
            }
        }
        return false;
    },

    isEmpty : function() {
        if (size) {
            return true;
        }
        return false
    }, 

    clear : function() {
        this.data = [];
    }
};

显然,我必须为可能使用数组的任何其他结构复制原型构造函数,但我想要完成的事情要清楚得多,即使是新手 JS 程序员也可以知道发生了什么。不仅如此,如果人们想要修改代码,他们确切地知道去哪里以及做什么。

我的建议是不要陷入试图让 JS 表现得像 C++ 或 Java 一样的疯狂。它永远不会。是的,你可以伪造继承和私有/公共/受保护的成员,但 JS 从来没有打算这样做。我认为拥有这种臃肿的代码(试图模拟非标准行为)对高性能网络应用程序及其同类应用程序的影响非常大。

简而言之,我建议使用对象文字:

var public_statics = {
    public_func: function () {},
    public_var: "hello"
}

它易于理解、易于修改和易于扩展。如果您的系统很脆弱,如果有人不小心更改了一些“私有”变量,就会崩溃和烧毁,那么您只需记录它。

于 2012-08-22T20:40:39.727 回答
1

我个人更喜欢 IIFE,因为您可以将方法设为私有。否则,您将不得不使用下划线进行某种奇怪的约定。

此外,从风格上讲,如果您将它封装在一个函数中,您可以选择制作分号 - 它是普通的旧 javascript。要求对象文字中的每一行都以逗号结尾对我来说似乎很有趣。

于 2012-08-22T20:20:06.780 回答
0

因为 JavaScript 语言本身以许多不同的方式实现,即每个浏览器都不同,所以您已经不得不从不一致开始。

JavaScript 不直接支持经典继承。(它支持原型继承)。

出于我的需要,我将选择不实现经典继承。这并不理想,因为经典继承允许您直接实现最佳实践 OO - 封装、继承和多态。

但是,我更喜欢等到该语言通过经典继承或类似方法直接支持 OO。

同时,我将只使用基本的原型继承来帮助实现代码重用。

于 2012-08-25T17:26:09.103 回答