這一直在困擾我一段時間。我正在設法考慮設計一個API的最佳方式,該API可以讓您訪問用戶需要的數據,但是基於API的其餘部分所依賴的一些內部對象。這裏有一個簡單的例子授予對內部對象的訪問權限,但防止外部修改?
function Person(name, ...) {
this.name = name;
this._friends = [];
...
}
Person.prototype.addFriend = function(friend){
this._friends.push(friend);
};
var bob = new Person("Bob", ...);
var alice = new Person("Alice", ...);
var tut = new Person("Tutankhamun", ...);
bob.addFriend(alice);
bob.addFriend(tut);
(我的理解前綴「私」與變量_並沒有真正從公衆隱藏。但我更喜歡使用重新定義構造函數內部所有的時間的原型。由於據我所知,你不能使用道格拉斯克羅克福德風格的私有變量與原型,我認爲這是一個不同的問題,無論如何。)
現在讓我們說我們想公開一種方式讓API用戶看到誰是鮑勃的朋友。最簡單的方法是返回朋友陣列:
Person.prototype.getFriends = function() {
return this._friends;
};
但是如果一些流氓開發者決定這樣做呢?
bob.getFriends().pop();
哦,親愛的,可憐的圖坦卡蒙。多麼可怕的誤會!鮑勃仍然喜歡圖坦卡蒙!我能想到的解決這個問題的唯一辦法是隻克隆對象的朋友一樣,每次這樣:
Person.prototype.getFriends = function() {
return this._friends.slice(0);
};
但你必須克隆它每一次。對於大型物體,這可能是一個問題。
那麼有沒有更好的方法來設計這個API來允許訪問內部數據而不允許修改?
[object.seal()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/seal)可能是一個更好的候選人,因爲他可能還想要修改現有的屬性,但防止添加/刪除。 – adamb
如果凍結對象,則不能在內部修改對象。密封可以防止你在這個例子中添加好友,這是一個有效的公共方法。 –