2011-12-04 176 views
1

当我编写代码的时候,我尝试将函数中的所有东西(方法,如果你喜欢的话)分开。功能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; 
    } 
} 

回答

5

这是一个在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; 
    } 
} 
+0

所有API和'user'都只是一个例子。 – daGrevis

+0

是的,我正在回答这个例子。 –

1

你说得对,“功能A确实是一件东西”。但是:对数据起作用的函数(从外部隐藏(或多或少))应该用数据做你想要的东西(例如添加一个用户)并且使得数据仍然是正确的(例如如果你有一个用户列表,增加UserCounter以使其始终正确)。 如果你想让你的API的用户为你做这个东西,反正不舒服。想象一下,您可以为用户列表添加更多功能(例如,告诉用户已将其添加到列表中,将用户存储在二叉树等中),并且您必须执行所有操作从你的函数外部组织东西,它的好处在哪里?

3

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

最终,我认为保持界面非常简单通常是件好事。抽象是一件好事。如果我正在使用别人的图书馆,我会非常失望地发现我希望手动增加这个值。

更新:

还有一两件事,我认为是值得一提的是:

通过让代码保持内部状态,并保持API的简单,你不仅让用户的生活更轻松,但你也防止滥用(在可能的范围内)。很容易想象某个人不正确地使用增量方法的情况,因此它会破坏某些东西。

+0

根据OP的具体例子:我的情绪正是如此。 –

1

我知道你只是希望示例代码是一个简单的例子,但像一个计数或长度变量的东西我想不出为什么我想永远不会让它独立于添加或删除项目的函数。当您使用该对象时,您不希望在每次添加时都需要调用add()increment()方法,而您真的不想在没有其他对象的情况下执行一个操作,或者您的对象最终以无效的状态。

所以我绝对不会以第一种方式来做,而且您在编辑中添加的方式肯定会更糟。让你的函数互相调用没有任何问题,但在你的例子中,我希望增量函数是私有的。

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

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