【问题标题】:Is encapsulation required for JavaScript objects?JavaScript 对象需要封装吗?
【发布时间】:2012-12-26 02:32:22
【问题描述】:

我正在开发一个 node.js 应用程序。寻找创建数据模型的方法。

发送到客户端/从客户端发送的数据是 JSON。由于数据库是 MongoDb,因此进出数据库的数据是 JSON。

我是 JS 新手,我可以找到很多专门用于创建封装对象的 js 库。还需要吗?

仅将模型定义为简单的 js 对象并在必要时使用基于原型的继承可能会产生什么后果?

感谢任何帮助。谢谢。

【问题讨论】:

    标签: javascript node.js mongodb data-modeling


    【解决方案1】:

    仅将模型定义为简单 js 的可能后果是什么 对象,并在必要时使用基于原型的继承?

    IMO,随着时间的推移,随着应用程序大小的增加或团队规模的增加,随着许多开发人员开始处理相同的代码,您将失去可维护性。

    换句话说 - 如果没有适当的封装,很容易修改不属于自己的对象 - 很容易干预你不想被触摸的部分。

    如果您正在编写某种库/框架,其中只有 API 向用户公开,而您没有适当的封装,则可能仅通过一次修改就可以降低所有内容。

    例如:

    var myObj = {
        mySecretPrivateCrucialFunction: function () {
            // all the awesome crucial logic
        },
        //This is what you want other parts of the code ...
        // ... to be interacting with in this object
        myPublicMethod: function () { 
                // some logic
            mySecretPrivateCrucialFunction(); 
                // some thing else
        }
    }
    

    我能做到。

    myObj.mySecretPrivateCrucialFunction = function () {
        alert('yay..i got you..');
    };
    

    但如果你这样做 - 你不会给那个机会。

    var myObj = (function () {
            var mySecretPrivateCrucialFunction = function () {
                    // all the awesome crucial logic
                }
            //This is what you want other parts of the code ...
            // ... to be interacting with in this object
            return {
                myPublicMethod: function () {} /*some logic */
                mySecretPrivateCrucialFunction(); /*some thing else */
            }
        })();
    

    如果您想将所有属性隐藏/私有,但仍想获取对象的 JSON 表示 - 您可以执行以下操作 -

    var myObj = (function () {
        // your private properties
        var prop1 = 1;
        var prop2 = 2;
        // your getters
        var getProp1 = function () {
                return prop1;
            };
        var getProp2 = function () {
                return Prop2;
            };
        // your setters
        var setProp1 = function (newValue) {
                prop1 = newValue;
            };
        var setProp2 = function (newValue) {
                prop2 = newValue;
            };
        // your JSON representation of the object
        var toString = function () {
                return JSON.stringify({
                    prop1: prop1,
                    prop2: prop2
                });
            };
        // Object that gets exposed -
        return {
            "getProp1": getProp1,
            "getProp2": getProp2,
            "setProp1": setProp1,
            "setProp2": setProp2,
            "toString": toString
        }
    })();
    

    【讨论】:

    • 谢谢。我同意这一点。但是如果对象只有字段而没有方法呢?补充一点,如果我像在 java 中那样隐藏对象的所有成员,JSON 字符串会发生什么?
    • 如果我理解正确的话,如果你隐藏了所有私有属性,并且像 Java 中的每个属性都有 getter 和 setter,你必须像在 Java 中那样在该对象中编写自己的“toString”函数,您可以使用它来获取该对象的 JSON 表示形式。
    • 编辑了我的答案以给出另一个具有隐藏属性的示例。看看吧。
    • 模块模式已经过时了,它是在所有人都试图封装和保护事物的时候创建的,因为受到 oop 语言的严重影响。今天没有人这样做,按原样使用javascript,不要试图封装和保护自己。事实上的标准说:“在变量名称前加上下划线来创建私有变量”,这就是你在 JS 中所需要的。
    • @Gabrel Llamas -“事实上的标准”是您无法严格执行且容易被滥用的标准,上述方法将解决我在大型应用程序中的一些维护问题。根据您的观察“今天没有人这样做” - 我不认为这是一个事实,这不是一个传播我个人观点的论坛,听说过 requireJS 及其受欢迎程度?
    【解决方案2】:

    在我看来,有两种方法可以解决这个问题:

    我假设您的数据正在作为 JSON 字符串传输。
    "[{\"key\":\"val\"}]" 出现在您的回复中,然后您将它们通过JSON.parse 将它们变成可行的数组和对象。

    所以第一种方法是制作“类实例”(不需要new 或继承,只是一个封装数据并根据数据类型公开接口的构造函数)。

    function makeTweet (data) {
        var tweet = {
                from_user : data.from_user || "anonymous",
                /* ... */
            },
    
            toString = function () {},
    
            public_interface : {
                toString : toString,
                /* getters, etc */
            };
        return public_interface;
    }
    

    我知道你已经知道这些东西,但是考虑一下在同一个进程中有两个或三个不同数据类型的情况(比如在行尾,当你准备打印到客户端),并且您有一个进程正在读取和写入每个对象上的公共字段。如果不同的对象具有不同的属性,那么事情的结局就会很糟糕,或者以一堆乏味的if 语句告终。

    另一种看待它的方式可能是实体/服务系统

    function handleTweets (tweetArr) {
        var templateFormat = system.output_format,
            string = "";
    
        if (templateFormat === "HTML") {
            string = HTMLtemplateTweets(tweetArr);
        } else { /* ... */ }
    }
    
    function HTMLtemplateTweets (tweetArr) {}
    function JSONtemplateTweets (tweetArr) {}
    function XMLtemplateTweets  (tweetArr) {}
    ...
    

    重点是您可以将 JSON 字符串转换为纯数据对象数组,并将它们提供给特定类型的库/系统函数行。

    这更像是一种非常简化的实体/系统方法,而不是一种 OO(传统上接受的)方法。

    现在,您的数据安全来自于确保您的对象只走一条预期的路径,因此该类型的每个对象的转换都是可预测的。

    如果您希望在 JS 中出于性能/内存目的“继承”,那么这也可能是一个值得关注的方向。

    【讨论】:

      猜你喜欢
      • 2010-12-03
      • 2011-03-24
      • 2018-10-17
      • 1970-01-01
      • 1970-01-01
      • 2016-08-01
      • 1970-01-01
      • 2011-05-06
      • 1970-01-01
      相关资源
      最近更新 更多