我有一個默認值的構造函數:如何確定對象屬性是否已直接分配或繼承?
var myObject = function(){
this.myValue = "default";
}
我然後實例化一個新的對象:
var newInstance = new myObject();
我如何判斷myValue
是原來的默認值,且尚未重新分配。我無法檢查價值,因爲它可能會被設置爲相同的,並且會產生誤報。
我有一個默認值的構造函數:如何確定對象屬性是否已直接分配或繼承?
var myObject = function(){
this.myValue = "default";
}
我然後實例化一個新的對象:
var newInstance = new myObject();
我如何判斷myValue
是原來的默認值,且尚未重新分配。我無法檢查價值,因爲它可能會被設置爲相同的,並且會產生誤報。
if (newInstance.hasOwnProperty('myValue')) {
// original default value
}
但是,這不能告訴你這是否發生了:
newInstance.myValue = 'default';
要檢測的是,你需要使用像getters/setters和跟蹤私人突變標誌:
function myObject() {
var _myValue = "default";
var _wasMutated = false;
return {
get myValue() {
return _myValue;
},
set myValue(x) {
_myValue = x;
_wasMutated = true;
},
get wasMutated() {
return _wasMutated;
}
}
}
// usage:
var newInstance = new myObject();
newInstance.myValue; // "default"
newInstance.wasMutated; // false
newInstance.myValue = "default";
newInstance.wasMutated; // true
newInstance.wasMutated = false; // writes have no effect since there's no setter
newInstance.wasMutated; // true
有來完成你要找的內容沒有內置的方式,但它是很容易做的一個「默認值「對象:
var MyObject = function() {
this.myValue = this.defaults.myValue
}
MyObject.prototype.defaults = { myValue: 'default' };
MyObject.prototype.isDefault = function(prop) {
return this[prop]===this.defaults[prop];
}
var o = new MyObject();
o.isDefault('myValue'); // returns true
o.myValue = 'foo';
o.isDefault('myValue'); // returns false
o.myValue = 'default';
o.isDefault('myValue'); // returns true
在另一方面,如果你需要知道什麼是與否的屬性曾經被設置(不管它的價值),你將不得不使用私有屬性和getter/setter方法功能:
var MyObject = function() {
var myValue = 'default'; // i'm private!
var myValueHasChanged = false;
this.myValue = function(newVal) {
if(arguments.length===0) {
return newVal;
} else {
myValue = newVal;
myValueHasChanged = true;
}
}
this.myValueHasChanged = function() {
return myValueHasChanged;
}
}
var o = new MyObject();
o.myValue(); // returns 'default'
o.myValueHasChanged(); // returns false
o.myValue('foo');
o.myValue(); // returns 'foo'
o.myValueHasChanged(); // returns true
o.myValue('default');
o.myValueHasChanged(); // returns true
+1。我可以建議'if(arguments.length === 0)'而不是'if(newVal === undefined)',以便可以將值設置爲'undefined'? – nnnnnn
這是一個很好的建議,@nnnnnn。我通常會避免*永遠*使用'undefined'作爲理所當然的事情(我認爲使用'undefined'保留給JS本身),但是你的建議確實會消除這個邊界情況,所以我會改變它。 –
我無法檢查的價值,因爲它可以被設置爲相同的,而且會產生假陽性。
如果你改變你的構造函數不設定值,而是把它放在原型:
var myObject = function(){};
myObject.prototype.myValue = "default";
...那麼你可以使用.hasOwnProperty()
method測試myValue
是否已經即使它被設置爲與默認值相同的值,也會覆蓋。
if (!newInstance.hasOwnProperty("myValue")) {
// has not been assigned another value
}
這工作,因爲如果你以後說:
newInstance.myValue = "something";
...這將在實例上直接創建myValue
屬性。當您使用newInstance .myValue
時,它會自動檢索直接屬性(如果存在)或否則將繼承原型屬性。
var newInstance = new myObject();
console.log(newInstance.myValue); // "default"
console.log(newInstance.hasOwnProperty("myValue")); // false
newInstance.myValue = "default";
console.log(newInstance.myValue); // "default"
console.log(newInstance.hasOwnProperty("myValue")); // true
這是一個有趣的方法(upvote!),但是與往常一樣,在原型上定義事物時,必須記住該屬性然後在所有實例之間共享(除非,正如您指出的那樣,它被覆蓋)。如果這可能讓你陷入困境,你的財產本身就是一個對象。考慮一下,然後'myObject.myValue.prop ='foo';'。現在所有未覆蓋'myValue'的'MyObject'實例都發生了變化,而且這種氣味就像一種副作用。 –
@EthanBrown - 你對屬性是完全正確的。對於那些當然你的方法或馬特的將覆蓋它。我承認我甚至沒有考慮過,因爲我只是想像OP的示例代碼中的字符串,但我認爲這對於那些原始值事例來說是合理的方法,因爲它使事情變得非常簡單。對於OP:謹慎使用。 – nnnnnn
更確切地說,它將使用任何不可變的值,因爲您只能通過爲它們分配新值來更改它們。因此,如果它們是不可變的(如String ojbect),它就可以處理對象。由於您可以使用.splice,.sort .push ...來更改它,因此無法與Array一起使用。 – HMR
我不認爲這是OP正在尋找的......他們想知道*值*是否已經改變; 'hasOwnProperty'不會告訴你這一點。 –
我不知道。我想知道它是否直接設置。不是它是否必然改變 –
啊,那麼@Matt Ball是正確的;你需要getters/setters。 –