在javascript的類中,可以用 __ defineGetter __和 __ defineSetter __控制成員變量的Get和Set行為。
image.png
在對象定義后給對象添加getter或setter方法要通過兩個特殊的方法defineGetter和defineSetter。這兩個函數要求第一個是getter或setter的名稱,以string給出,第二個參數是作為getter或setter的函數。
例如我們給Date對象添加一個year屬性:
Date.prototype.__defineGetter__('year', function() {return this.getFullYear();});
Date.prototype.__defineSetter__('year', function(y) {this.setFullYear(y)});
var now = new Date;
alert(now.year);
now.year = 2006;
alert(now);
不過,這兩個屬性已經被廢棄,所以并不推薦大家去使用。咱們今天的主角是defineProperty。
Object.defineProperty() 方法會直接在一個對象上定義一個新屬性,或者修改一個對象的現有屬性, 并返回這個對象。
語法:Object.defineProperty(obj, prop, descriptor)
obj
需要被操作的目標對象
prop
目標對象需要定義或修改的屬性的名稱。
descriptor
將被定義或修改的屬性的描述符。
返回值
被傳遞給函數的對象。
目前常用示例: Setters 和 Getters
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 }]
or
var pattern = {
get: function () {
return 'I alway return this string,whatever you have assigned';
},
set: function () {
this.myname = 'this is my name string';
}
};
function TestDefineSetAndGet() {
Object.defineProperty(this, 'myproperty', pattern);
}
var instance = new TestDefineSetAndGet();
instance.myproperty = 'test';
// 'I alway return this string,whatever you have assigned'
console.log(instance.myproperty);
// 'this is my name string'
console.log(instance.myname);
實際運用
在一些框架,如vue、express、qjs等,經常會看到對Object.defineProperty的使用。那這些框架是如何使用呢?
MVVM中數據‘雙向綁定’實現
如vue,qjs等大部分mvvm框架(angular用的是臟處理)都是通過Object.defineProperty來實現數據綁定的 下面篇幅先不展開。(別扔磚。。。)
兼容
最后注意下,Object.defineProperty是ES5的屬性,大部分場景使用是沒問題的,移動端可以放心用, 但在一些場景如IE8以下是使用不到的哈。