【问题标题】:Coding Style in node.jsnode.js 中的编码风格
【发布时间】:2014-02-26 10:18:39
【问题描述】:

样式 1:带有构造函数/原型的对象

function DB(url) {
    this.url = url;
}

DB.prototype.info = function (callback) {
    http.get(this.url + '/info', callback);
};

样式 2:闭包

function DB(url) {
    return { info: async.apply(http.get, url + '/info') };
}

这只是一个例子,假设涉及更多原型方法和私有方法。

我在帖子OneTwo 中读到,在nodejs 中,闭包风格比另一种更受欢迎。请帮助我澄清为什么在 nodejs 中使用 this.something 语法不好。

你可以给出你的意见,哪个更好,但我主要需要知道在 nodejs 中使用时每种样式的优缺点是什么

【问题讨论】:

    标签: javascript performance node.js syntax coding-style


    【解决方案1】:

    这与风格无关。这两个函数做了两件完全不同的事情。

    闭包提供对局部变量的访问。通过这种方式,您可以创建无法从外部访问的私有变量(例如您的示例中的 url)。但它会影响性能,因为每次创建对象时都会创建闭包。

    原型函数比较快,但是它是在对象之前创建的,对对象本身一无所知。

    有时同时使用它们甚至是有意义的。 :)

    PS:这里描述了编码风格:https://npmjs.org/doc/coding-style.html。它没有解释您的特定问题,但我觉得我必须在先前答案中的这两个链接与更明智的东西之间取得平衡。 :)

    【讨论】:

    • 同时使用两者有意义是什么意思?我认为您指的是我应该根据我正在编写的那段特定代码的需要使用它们。但如果是这样的话,我想知道我应该使用哪种情况......那是我的问题
    • “两者同时”表示根据传递给构造函数的选项覆盖某些方法的能力。如果您不知道我在说什么,请使用prototype,因为它更快。
    • 你能推荐一个同时使用两者的例子吗?完全没看懂。
    • This 就是一个很好的例子。
    【解决方案2】:

    闭包在正确完成后,允许您通过使用任何其他调用者无法修改的范围链来封装数据。

    原型链不提供同样意义上的任何保护。以您描述的方式使用对象的主要缺点,特别是在服务器或库场景中,是调用者可以修改“this”关键字。你无法控制它,如果发生这种情况,你的代码将以不可预知的方式中断。

    var mongo = new DB('localhost');
    mongo.info.call(this);  // broken
    

    现在它可能不会像那样显式地发生,但是如果您将对象或对象属性作为事件处理程序、回调等传递给其他函数,您将无法知道或防止这种用法。所以底线是'this'关键字不是你可以依靠的东西。虽然您可以使用闭包完全控制您的直接作用域。

    同样,您也不能保证您的对象的原型链没有被更改。当然,除非您在对象上创建一个闭包并返回一个包装器。

    最后,闭包结构更符合得墨忒耳定律,因为理论上,您的对象将通过原型链“到达”。使用闭包封装其他调用允许您公开单个方法,这可能导致调用另一个服务方法。这提供了更大的可维护性和灵活性,因为您现在可以直接控制您公开的方法,而无需依赖原型链。当然,LoD 只是做事的一种方式,所以它对你来说可能重要也可能不重要。

    【讨论】:

    • 所以你倾向于在 api 必须公开的情况下使用闭包,如果它是一个仅由我开发的内部应用程序,那么我认为原型是安全的?
    • 是的,无论如何都不会有内在的性能问题。这是一种风格选择,闭包受到更多保护——比其他任何东西都更接近私有实例变量。但是有一些框架和插件可以同时做到这一点,所以它最终是给你的。我还要指出,至少恕我直言,CommonJS 模块使闭包易于使用。但这取决于您的喜好。
    【解决方案3】:

    节点遵循 javascript 标准。所以任何 javascript 编码风格都是适合 node.js 的编码风格。但是下面的链接可能会给你 node.js 编码风格的缩写。

    http://nodeguide.com/style.html

    http://innofied.com/javascript-coding-standards-follow/

    【讨论】:

    • 但这两个链接都没有谈到我提到的特定风格。 N 其次,我认为你说 node 遵循 javascript 样式是错误的,因为 NODE 是一个不同的平台,它可以具有浏览器中不典型的 javascript 的各种约定和样式。
    • JavaScript 的编码标准对于任何平台都应该是相同的。这可能取决于使用情况。节点中的回调函数、事件和许多东西与基本的 JavaScript 相同
    • @Saransh 节点 Javascript。除了 Javascript,你不能用任何其他风格编写 Node。
    【解决方案4】:

    我使用sjsClasshttps://www.npmjs.org/package/sjsclass

    代码示例:

    Class.extend('DB', {
        'protected url': null,
    
        __constructor: function (url) {
            this.url = url;
        },
    
        info: function (callback) {
            http.get(this.url + '/info', callback);
        }
    });
    

    【讨论】:

      【解决方案5】:

      这两种样式都有好处,我认为这取决于您的模块/文件试图公开的内容。我在代码中使用的大多数模块都大量使用闭包样式。 (如数据库抽象、缓存抽象、邮件等)并且我使用构造函数/原型来创建大量对象(如双向链表中的节点)

      === 具有在闭包内定义的属性的对象

      如果你创建一个对象(让我们称之为 self), 在其范围内添加一堆访问并附加到该对象的方法(self.x) 最后导出自我,一切都只能访问您添加到自我的内容,而无法访问您创建自我的函数内的局部变量

      === 构造函数和原型

      另一方面,如果您创建构造函数并通过原型向它们添加方法/字段,则每个附加到您的实例的函数都可以访问其内部变量和状态。

      ==

      使用 EventEmitter 之类的原型可以更轻松地完成一些事情 和 Streams,但也不是很难将它们附加到对象上。

      Javascript 既是面向对象语言又是函数式语言,两者都缺少繁重的工具

      喜欢正确的继承 this.super().super().someMethod() ??我没有 (如果两个超类具有相同的方法名,则需要它)

      或游牧民族或函数式编程方面的简单生成器。

      所以对我来说,两者都使用是有意义的,并选择最适合您的问题的一个。

      编辑

      我完全忘记的对象有一个很大的好处。 在您的第二个示例中,您使用了流控制库(在这种情况下为异步,但任何延迟库都可以),但是它使您的代码更加简洁

      为了让您的示例正常工作,http.get 的 get 方法必须绑定到 http,但在许多情况下并非如此。那么你的代码看起来像 http.get.bind(http) 如果 http 是一个对象并且 get 是在其范围内定义的,那么它将始终有效并允许您将其传递给其他代码。 (如异步)

      【讨论】:

        【解决方案6】:

        恕我直言,这是比节点更大的讨论......它是关于 javascript 语言的。

        所以我建议阅读:

        http://addyosmani.com/resources/essentialjsdesignpatterns/book/

        和 google 一些关于 javascript 设计模式的知识!

        【讨论】:

          【解决方案7】:

          构造函数可以这样使用

          var db = new DB();
          ...   
          if(db instanceof DB){
              ...
          }
          

          闭包可以使私有变量像

          function DB(url) {
              var urlParam = '&a=b';
              return { 
                  info: async.apply(http.get, url + '/info' + urlParam) 
              };
          }
          

          urlParam 是私有变量,无法获取或设置

          如果您只想要一个静态类或简单类,请使用闭包。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2014-03-10
            • 1970-01-01
            • 2016-03-21
            • 2016-01-05
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多