【问题标题】:Calling function inside of function在函数内部调用函数
【发布时间】:2012-01-12 20:05:31
【问题描述】:

当我编写代码时,我会尝试将所有内容划分为函数(方法,如果你喜欢的话)。函数 X 处理 X,Y 处理 Y 并且 像方法 X 处理 X、Y 和 Z!这给了我更多可重用的代码。我喜欢。 :)

让我们看看这段代码:

var user = {
  users: [],
  userCount: 0,
  addUser: function(user) {
    (this.users).push(user);
  },
  incrementCount: function() {
    ++this.userCount;
  }
}

var user = { // 2nd example.
  users: [],
  userCount: 0,
  addUser: function(user) {
    (this.users).push(user);
    ++this.userCount;
  }
}

(它在 JavaScript 中,但这里的语言不是必需的。)

在我看来,第二个示例对于 API 用户来说会更容易且更安全。 很容易忘记拨打user.incrementCount()。你怎么看?第二个示例自动执行。

那么如何找到平衡点呢?关于在函数内部调用函数的任何最佳实践?

感谢您阅读本文。

编辑

我刚才想到了这个:

var user = {
  users: [],
  userCount: 0,
  addUser: function(user) {
    (this.users).push(user);
    this.incrementCount();
  },
  incrementCount: function() {
    ++this.userCount;
  }
}

【问题讨论】:

    标签: javascript oop coding-style code-reuse


    【解决方案1】:

    在 JS 中有点不同,因为在使用对象字面量表示法时没有办法让函数真正私有,但是...

    这完全取决于您希望您的对象向其消费者公开的 API。您是否希望 API 的消费者能够在添加用户的同时增加计数?如果是这样:

    { addUser: /* snip */, incrementCount: /* snip */ }
    

    否则:

    { addUser: /* snip */, _incrementCount: /* snip */ }
    // or just
    { addUser: /* snip */ }
    

    在这种特殊情况下,我强烈建议您不要存储任何单独的计数,因为 users 数组已经为您做到了。

    var user = {
      _users: [],
      addUser: function(user) {
          this._users.push(user);
      },
      getUserCount: function () {
          return this._users.length;
      }
      // and if you need to expose the users array directly,
      , getUsers: function () {
          return this._users;
      }
    }
    

    【讨论】:

    • 所有 API 和 user 只是一个例子。
    • 是的,我根据那个例子来回答。
    【解决方案2】:

    就个人而言,我认为您甚至不应该通过 API 公开这些内容。此外,使用users.length 会更容易(至少在 JavaScript 中)更直观。

    最终,我认为保持界面非常简单通常是一件好事。抽象是个好东西。如果我使用的是其他人的库,我会非常失望地得知我需要手动增加该值。

    更新:

    还有一点我觉得值得一提:

    通过让您的代码在内部维护状态并保持 API 简单,您不仅可以让用户的生活更轻松,还可以防止滥用(在可能的范围内)。很容易想象有人错误地使用了该增量方法,结果会破坏东西。

    【讨论】:

    • 基于 OP 的特定示例:完全是我的观点。
    【解决方案3】:

    你说的“功能 A 做 A-Stuff”是对的。 但是:一个处理数据的函数,从外部隐藏(或多或少),应该对数据做你想要的事情(例如添加一个用户)并确保数据仍然是正确的(例如,如果您有一个用户列表,增加 Usercounter 以使其始终正确)。 如果您离开希望您的 API 的用户为您做这些事情,那无论如何都不舒服。

    想象一下,您向用户列表添加更多功能(例如,告诉用户它已添加到列表中,将用户存储在二叉树中等等),而您必须完成所有组织来自你的功能之外的东西,它的好处在哪里?

    【讨论】:

      【解决方案4】:

      我知道您只是打算将示例代码作为一个简单的示例,但是对于计数或长度变量之类的东西,我想不出为什么我想让它独立于添加或删除项目的函数。使用对象时,您不想每次添加时都调用add() increment() 方法,而您真的不想能够在没有另一个的情况下做一个,否则您的对象最终会处于无效状态。

      所以我永远不会使用第一种方式,而且您在编辑中添加的方式肯定更糟糕。让你的函数相互调用没有错,但在你的例子中,我希望增量函数是私有的。

      最好将 count 变量设为私有,只允许通过函数检索它并通过添加/删除函数进行设置(尽管当您可以返回 users.length 时,您甚至不需要 count 变量)。以下带有立即执行的匿名函数的模式允许您拥有私有变量和函数,并且您只返回一个包含公共函数的对象。公共函数仍然可以访问私有变量/函数,但不能从外部访问私有的东西。

      var user = (function() {
         var users = [],    // private variables
             private1,
             private2;
      
         function privateFunction1() { /* do something */ }
      
         return {
            getUserCount : function() {
                             return users.length;
                           },
            addUser:       function(user) {
                             users.push(user);
                             // return index of new user
                             return users.length - 1;
                           },
            getUser :      function(userIndex) {
                             return users[userIndex];
                           },
            someFunc :     function(someParam) {
                             return someParam + privateFunction1();
                           }
         }
      })();
      
      user.addUser("Fred");
      user.addUser("Mary");
      console.log(user.getUserCount()); // 2
      console.log(user.getUser(1));     // Mary
      

      【讨论】:

        猜你喜欢
        • 2017-12-06
        • 1970-01-01
        • 1970-01-01
        • 2017-03-05
        • 2021-02-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-09-22
        相关资源
        最近更新 更多