[英]Prototype of defineProperty in JavaScript
在JavaScript中,您可以使用Object.defineProperty()
定義getter和setter。 我想知道是否可以擴展或使用它的原型來擴展其功能。 這是一個例子:
我開始一個名為color的變量:
Object.defineProperty(window, 'color', {
get: function() {
return [_color.red,_color.green,_color.blue,_color.alpha];
},
set: function(val) {
_color.red = val[0];
_color.green = val[1];
_color.blue = val[2];
_color.alpha = val[3];
}
});
這允許我通過將rgba數組傳入和傳出變量來設置和獲取顏色。 以下是我將如何使用它:
color = [0,127,255,255];
alert(color);
//alerts [0,127,255,255]
現在我也想通過單獨訪問每個變量來編輯這些變量。
color.r = 255;
alert(color);
//alerts [255,127,255,255]
我此刻陷入僵局,因為我不知道我能做些什么來創造這個。 我會認為使用color.prototype.r
或類似的東西可以工作,但我不能得到它。 可以這樣做嗎?
您必須創建從數組擴展的臨時對象才能專門執行此操作。
干得好:
var __color = {red:0,green:0,blue:0,alpha:1};
function createGetMethod(prop){
return function(){return __color[prop]};
}
function createSetMethod(prop){
return function(val){__color[prop]=val};
}
function createDescritorProperty(prop){
return {
get: createGetMethod(prop),
set: createSetMethod(prop)
}
}
var _color_descriptor = {
red:createDescritorProperty('red'),
green:createDescritorProperty('green'),
blue:createDescritorProperty('blue'),
alpha:createDescritorProperty('alpha'),
length:{
value:4,
writable:false
}
}
//setup numbered values
_color_descriptor[0]=createDescritorProperty('red');
_color_descriptor[1]=createDescritorProperty('green');
_color_descriptor[2]=createDescritorProperty('blue');
_color_descriptor[3]=createDescritorProperty('alpha');
var _color = Object.create(Array.prototype, _color_descriptor); //extends array
Object.defineProperty(window, 'color', {
get: function() {
return _color;
},
set: function(val) {
_color.red = val[0];
_color.green = val[1];
_color.blue = val[2];
_color.alpha = val[3];
}
});
window.color = [255,255,255,0];
alert(window.color);
window.color.red=10;
alert(window.color);
希望它有效! :d
prototype
僅適用於對象實例,遺憾的是您沒有。 如果你有這樣的構造函數:
function Color(r,g,b,a){
for (var i=0; i<4; i++)
this[i] = arguments[i];
}
它會合作
Object.defineProperty(Color.prototype, "r", {
get: function() { return this[0]; } // setter analogous
};
但是,這些Color
實例不是數組。 你可以給它們一個length
屬性,讓它們從Array.prototype
繼承,但它們實際上不是數組。 @Trouts解決方案有點像這樣,我說它沒關系,因為顏色確實沒有數組(你不能推第五個值等)。
另一種方法是使用這些屬性擴展從color
吸氣劑返回的數組。 每次有人訪問該值時你都可以這樣做(就像你現在一樣,你在getter中創建一個新數組)但是我建議你應該返回相同的實例,傳播任何更改。 您當前的屬性定義類似於“setColor”和“getCurrentColor”。
所以,實際上你需要兩個獨立的東西:每個值具有多個屬性的Color
對象(即0
== r
); 和一個全局color
變量的setter,它接受數組並在相應的對象上設置單個值。
// version with private values
function Color(r, g, b, a) {
// r, g, b and a are private-scoped variables
var desc = {
"0": {
get:function(){return r;},
set:function(val){ if(+val<256&&val>=0) r=+val;}
},
…
}
// use those property descriptors multiple times
desc.r = desc[0];
…
Object.defineProperties(this, desc);
}
// or version with public and unlimited read/write access to the properties:
function Color(r,g,b,a){
for (var i=0; i<4; i++)
this[i] = arguments[i];
}
Object.defineProperties(Color.prototype, {
r: { get:function(){return this[0];}, set:function(r){this[0]=r;} },
…
}
// and for both versions we can add array-like methods on the prototype
var cprot = Color.prototype, aprot = Array.prototype;
Object.defineProperty(cprot, "length", {value:4});
// we only need accessor functions here, nothing which changes the array [length]
cprot.map = aprot.map;
cprot.reduce = aprot.reduce;
cprot.slice = aprot.slice;
cprot.join = aprot.join;
// you might want to add other utilities like
cprot.toString = function() {
return "rgba("+this.join(",")+")"; // using array method from above
};
cprot.getHex = function() {
function hex(n) { return (n<16?"0":"") + n.toString(16); }
return "#"+this.slice(0, 3).map(hex).join("");
};
然后,你的顏色值設定器:
function defineColorProperty(obj, prop, color) {
// again, color is private-scoped
if (!color || !(color instanceof Color)) color = new Color(0, 0, 0, 0);
Object.defineProperty(obj, prop, {
get: function(){ return color; }, // a cool Color instance!
set: function(val) {
if (Object(val)!==val) return; // accept objects (including arrays)
for (var i=0; i<4 && i<val.length; i++)
color[i] = val[i];
},
enumberable: true
});
return color;
}
// usage:
> defineColorProperty(window, "color");
Object[Color]: 0, 0, 0, 0
> color = [255, 0, 120, 1];
> color.r = 42;
> color[0]
42
> color = [0, 0];
> ""+color
"rgba(0,0,120,1)"
> var x = color;
> x.b = 255;
> x.getHex()
"#0000FF"
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.