2011-12-04 234 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