[英]Implementing setter and getter in JavaScript object
我想在本地javascript變量上實現setter和getter。 這是一個示例函數:
function someThing() {
var someLocalvariable = '';
}
// with this function I want to
// return value of someLocalvariable
// also if it is possible to implement
// setter in this way.
someThing.prototype.getLocalVar = function() {
}
我想變量'真的'私有。 我不會使用這樣的東西:someThing.prototype.someLocalvariable =
要么
function someThing() {
this.someLocalvariable = '';
}
或者在someThing()中附加函數,如下所示:
function someThing() {
var someLocalvariable = '';
this.getLocalvariable = function() {
return someLocalvariable;
}
}
我將非常感謝任何指導和幫助。
你不想做的最后一個例子是不行的(它有語法錯誤), (它已被修復)但我認為你可能意味着這樣做的常用方法,即制作getter和setter構造函數中的閉包(如下)。
不幸的是,如果你想要真正的私有變量,這只是你唯一的選擇。 沒有其他方法可以獲得真正私有的, 特定於實例的變量。 但是,請參閱下面的“黑客”。
這是通常的做法的正確版本(我認為你說你不想要,但為了完整性):
function SomeThing() {
var privateVar;
this.setPrivateVar = function(val) {
privateVar = val;
};
this.getPrivateVar = function() {
return privateVar;
};
}
// use:
var t = new Something();
t.setPrivateVar("foo");
console.log(t.getPrivateVar()); // "foo"
像大多數人一樣,我首先在Douglas Crockford的網站上閱讀過這種模式。
這個選項確實有缺點:通過SomeThing
構造函數創建的每個實例都有自己的兩個函數。 它們不能在實例之間共享。 因此,如果您的應用程序SomeThing
有數百或數千個SomeThing
實例,那么從內存角度考慮這一點。 如果有幾百個或更少,那可能無關緊要。 (這些數字是從帽子中拉出來的,你不應該相信它們,當你出現某種問題時,你必須檢查代碼的內存使用情況;但是你明白了。)
黑客攻擊:如果你的實例已經有一些獨特的標識符作為公共數據(或者你願意添加一個,那么它將是公開的),如果你願意添加一些復雜的在使用實例時,您可以擁有一個私有緩存,用於保存只有您的代碼可以訪問的所有實例的數據,並通過對象的唯一標識符鍵入該緩存。 像這樣(在這個例子中,我正在分配id
值,但是你可以使用現有的唯一ID):
var SomeThing = (function() {
var cache = {}, idAllocator = 0;
function SomeThing() {
this.id = ++idAllocator; // The unique identifier, can be a string if desired
cache[this.id] = {};
}
SomeThing.prototype.getPrivateVar = function() {
var data = cache[this.id];
return data && data.privateVar;
};
SomeThing.prototype.setPrivateVar = function(value) {
cache[this.id].privateVar = value;
};
SomeThing.prototype.destroy = function() {
delete cache[this.id];
};
return SomeThing;
})();
這是如何工作的:所有函數都是外部作用域函數中cache
局部變量的閉包。 我們使用對象的唯一ID對其進行索引,這為我們提供了一個對象,我們將其放在私有數據成員上。 當使用實例的代碼完成后,該代碼必須調用destroy
(這是此模式的主要缺點),因此我們通過刪除id
的屬性從cache
刪除私有數據對象。
警告和費用:
id
) SomeThing
創建的實例的用戶必須在完成這些實例后調用destroy
。 這是JavaScript的垃圾處理工作方式的詛咒,但它是上述模式的要求,否則你最終會在cache
對象中建立起來。 id
值,如果你的應用創建並銷毀了很多這些實例,你將會用完它們。 但是JavaScript的數字確實非常高,如果這是一個問題,只需找到一種不同的方式來分配ID,而不是上面簡單的常設增長系統。 我還沒有在我的工作中使用上面的模式,但我希望它有一些用例,涉及數千個SomeThing
實例,因此不希望有每個實例的功能。
附注:在上面,我將someThing
更改為SomeThing
。 在JavaScript中,標准做法是將普通函數的名稱以小寫字母開頭,並將構造函數的名稱(與new
一起使用的名稱)以大寫字母開頭。 由於SomeThing
是用於new
,我限制了它。 這只是慣例,但它是一個非常受歡迎的慣例,當然,它在語言定義本身中使用( Date
是構造函數, setHours
是函數)。
在函數構造函數中使用Object.defineProperty(),以便在此處定義getter和setter 更多信息 。
要使真正的私有(對外部不可見),某些值使用Closure,可以在此處找到更多信息。
在下面的示例中,我們為屬性temperature
定義了一個getter和setter,其中內部“private”值存儲在變量var temperature
。
var temperature
永遠不會從Archiver()
的外部可見/可訪問它是一個閉包。
請注意,此模式在ES5上作為Object.defineProperty()在ES3上不受支持。
function Archiver() {
var temperature = null;
var archive = [];
Object.defineProperty(this, 'temperature', {
get: function () {
console.log('get!');
return temperature;
},
set: function (value) {
temperature = value;
archive.push({ val: temperature });
}
});
this.getArchive = function () {
return archive;
};
}
var arc = new Archiver();
arc.temperature; // 'get!'
arc.temperature = 11;
arc.temperature = 13;
arc.getArchive(); // [{ val: 11 }, { val: 13 }]
像這樣的東西:
function Field(val){ var value = val; this.getValue = function(){ return value; }; this.setValue = function(val){ value = val; }; } var field = new Field("test"); field.value // => undefined field.setValue("test2") field.getValue()
檢查參考: http : //ejohn.org/blog/javascript-getters-and-setters/
道格拉斯Crockford的寫了這對在JavaScript中實現私有成員
那是不可能的。 如果你在someThing()中有一個局部變量,你附加到原型的函數就無法讀取它的值(它是私有的,還記得嗎?)。 你的最后一個例子是這個問題的正常解決方案,為什么這對你來說不夠好?
嘗試這兩種方法來實現setter和getter
var address = {
street : "No street",
city : "No city",
state : "No state",
get getAddress()
{
return (this.street+","+this.city+","+this.state);
},
set setAddress(theAddress)
{
var part = theAddress.toString().split(", ");
this.street = part[0] || "";
this.city = part[1] || "";
this.state = part[2] || "";
}
};
address.setAddress = "27 Sus Road, Pune, MH";
console.log(address.getAddress);
//Other setter and getter
function Square(side)
{
this._side = side;
};
Square.prototype = {
set setSide(side){
this._side = side;
},
get getSide(){
return this._side;
},
get getArea(){
return (this._side * this._side);
}
};
var mySquare = new Square(10);
mySquare.setSide = 15;
console.log("Area of square is "+mySquare.getArea+" with side "+mySquare.getSide);
第一種方法
var address = {
street : "No street",
city : "No city",
state : "No state",
get getAddress()
{
return (this.street+","+this.city+","+this.state);
},
set setAddress(theAddress)
{
var part = theAddress.toString().split(", ");
this.street = part[0] || "";
this.city = part[1] || "";
this.state = part[2] || "";
}
};
address.setAddress = "27 Sus Road, Pune, MH";
console.log(address.getAddress);
第二種方法
function Square(side)
{
this._side = side;
};
Square.prototype = {
set setSide(side){
this._side = side;
},
get getSide(){
return this._side;
},
get getArea(){
return (this._side * this._side);
}
};
var mySquare = new Square(10);
mySquare.setSide = 15;
console.log("Area of square is "+mySquare.getArea+" with side "+mySquare.getSide);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.