1

JavaScriptでは、を使用してゲッターとセッターを定義できますObject.defineProperty()。このプロトタイプを拡張または使用して機能を拡張することは可能かどうか疑問に思っています。次に例を示します。

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か、似たようなものでうまくいくと思いますが、うまくいきません。このようなことは可能ですか?

4

2 に答える 2

2

具体的には、配列から拡張された暫定オブジェクトを作成する必要があります。

どうぞ:

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

于 2012-09-26T11:25:26.960 に答える
1

これ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ソリューションはそのようなものですが、色は実際には配列ではないため(5番目の値をプッシュすることはできません)、問題ないと思います。

color別の方法は、ゲッターから返す配列をこれらのプロパティで拡張することでした。誰かが値にアクセスするたびにそれを行うことができますが(現在のように、ゲッターで新しい配列を作成します)、変更を伝播して同じインスタンスを返すことをお勧めします。現在のプロパティ定義は「setColor」や「getCurrentColor」のようなものです。

したがって、実際には2つの別個のものが必要です。Color値ごとに複数のプロパティを持つオブジェクト(つまり、 0== r)。color配列を受け入れ、それぞれのオブジェクトに単一の値を設定するグローバル変数のセッター。

// 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"
于 2012-09-26T12:13:00.290 に答える