Getter/setter javascriptの配列?
-
20-09-2019 - |
質問
がわかりやすく伝えるためのget/set行動基配列?思うようになります:
var arr = ['one', 'two', 'three'];
var _arr = new Array();
for (var i = 0; i < arr.length; i++) {
arr[i].__defineGetter__('value',
function (index) {
//Do something
return _arr[index];
});
arr[i].__defineSetter__('value',
function (index, val) {
//Do something
_arr[index] = val;
});
}
解決
アレイへのアクセスは、通常のプロパティへのアクセスに違いはありません。あなたはそれを介して第1の配列項目に名前array[0]
と切片アクセスのプロパティを定義することができるようにarray['0']
は、'0'
を意味します。
しかし、すべてが、短い、多かれ少なかれ、固定長の配列のため、それは非現実的にするん。あなたが一度にすべての「整数であることを起こるすべての名前」のプロパティを定義することはできません。
他のヒント
プロキシを使用して、あなたが得ることができます望ましい行動ます:
var _arr = ['one', 'two', 'three'];
var accessCount = 0;
function doSomething() {
accessCount++;
}
var arr = new Proxy(_arr, {
get: function(target, name) {
doSomething();
return target[name];
}
});
function print(value) {
document.querySelector('pre').textContent += value + '\n';
}
print(accessCount); // 0
print(arr[0]); // 'one'
print(arr[1]); // 'two'
print(accessCount); // 2
print(arr.length); // 3
print(accessCount); // 3
print(arr.constructor); // 'function Array() { [native code] }'
<pre></pre>
プロキシコンストラクタは、基本的な動作をオーバーライドするために、トラップと呼ばれる私たちの配列と使用機能をラップするオブジェクトを作成します。 get
関数は値を返す前にのいずれかののプロパティの検索、およびdoSomething()
のために呼び出されます。
プロキシはES6機能であり、IE11以下でサポートされていません。 ブラウザの互換性リストを参照してください。こちら
私はジョンResig氏の記事に JavaScriptのgetterとsetter に見上げたが、彼の試作例は私のために動作しませんでした。いくつかの選択肢を試した後、私は仕事に見えたものを見つけました。あなたは次のようにArray.prototype.__defineGetter__
を使用することができます:
Array.prototype.__defineGetter__("sum", function sum(){
var r = 0, a = this, i = a.length - 1;
do {
r += a[i];
i -= 1;
} while (i >= 0);
return r;
});
var asdf = [1, 2, 3, 4];
asdf.sum; //returns 10
ChromeとFirefoxで私のために働いています。
私はそれが役に立てば幸います。
Object.extend(Array.prototype, {
_each: function(iterator) {
for (var i = 0; i < this.length; i++)
iterator(this[i]);
},
clear: function() {
this.length = 0;
return this;
},
first: function() {
return this[0];
},
last: function() {
return this[this.length - 1];
},
compact: function() {
return this.select(function(value) {
return value != undefined || value != null;
}
);
},
flatten: function() {
return this.inject([], function(array, value) {
return array.concat(value.constructor == Array ?
value.flatten() : [value]);
}
);
},
without: function() {
var values = $A(arguments);
return this.select(function(value) {
return !values.include(value);
}
);
},
indexOf: function(object) {
for (var i = 0; i < this.length; i++)
if (this[i] == object) return i;
return -1;
},
reverse: function(inline) {
return (inline !== false ? this : this.toArray())._reverse();
},
shift: function() {
var result = this[0];
for (var i = 0; i < this.length - 1; i++)
this[i] = this[i + 1];
this.length--;
return result;
},
inspect: function() {
return '[' + this.map(Object.inspect).join(', ') + ']';
}
}
);
定義することが可能でsetterか、セッターのためにJavaScriptをarrays.ができませんのでご了承くださいaccessors価値でも同時に行います。のMozilla 文書:
できないので同時において、ゲッター行きホテルグランドパレスのすぐ横にしている物件を実際に値を保持する
で設定されていない場合はaccessorsのための配列が必要となり次配列の実際の値です。以下の 例 を示します。
//
// Poor man's prepare for querySelector.
//
// Example:
// var query = prepare ('#modeler table[data-id=?] tr[data-id=?]');
// query[0] = entity;
// query[1] = attribute;
// var src = document.querySelector(query);
//
var prepare;
{
let r = /^([^?]+)\?(.+)$/; // Regular expression to split the query
prepare = function (query, base)
{
if (!base) base = document;
var q = []; // List of query fragments
var qi = 0; // Query fragment index
var v = []; // List of values
var vi = 0; // Value index
var a = []; // Array containing setters and getters
var m; // Regular expression match
while (query) {
m = r.exec (query);
if (m && m[2]) {
q[qi++] = m[1];
query = m[2];
(function (qi, vi) {
Object.defineProperty (a, vi, {
get: function() { return v[vi]; },
set: function(val) { v[vi] = val; q[qi] = JSON.stringify(val); }});
})(qi++, vi++);
} else {
q[qi++] = query;
query = null;
}
}
a.toString = function () { return q.join(''); }
return a;
}
}
このコードは三つの配列:
- 一つの価値観
- のJSONで符号化された値
- 一つのaccessors.
配列のaccessorsを返して、呼び出し側に返します。の場合 set
によって呼び出されると価格を、配列要素の配列を含む平野および符号化された値を更新しました。時 get
くというを返します。での値です。や toString
を返します全体を含むクエリの符号化された値です。
しかしその他は既に:これだけの意味では、サイズの配列が一定になります。を修正することができます既存の配列の要素ができない追加。
なぜ、内のオブジェクトの新しいクラスを作成していない?
var a = new Car();
function Car()
{
// here create the setters or getters necessary
}
そして、
arr = new Array[a, new Car()]
私はあなたのアイデアを得ると思います。
を作成することができセッターの各要素の配列が多いですが、制限:ることはできませんが直接設定の配列要素のための指標に初期化された領域( myArray[2] = ... // wouldn't work if myArray.length < 2
の配列になります。試作機能します。(例:押し、ポップス、スプライス、シフト、unshift.) 私に与えるこ こちらの.
あなたはArray
に追加することによって、Array.prototype
に好きな方法であなたを追加することができます。ここではゲッターとセッターを追加する例を示します。
Array.prototype.get = function(index) {
return this[index];
}
Array.prototype.set = function(index, value) {
this[index] = value;
}
これは、私は物事を行う方法です。あなたは(私は私のバージョンからのビットを削除)プロトタイプの作成を微調整する必要があります。しかし、これはあなたに私が他のクラスベース言語にするために使用していますデフォルトのゲッター/セッターの動作を提供します。 ゲッターとセッターがないの定義要素への書き込みが無視されることを意味します...
この情報がお役に立てば幸いです。
function Game () {
var that = this;
this._levels = [[1,2,3],[2,3,4],[4,5,6]];
var self = {
levels: [],
get levels () {
return that._levels;
},
setLevels: function(what) {
that._levels = what;
// do stuff here with
// that._levels
}
};
Object.freeze(self.levels);
return self;
}
これは私の予想される動作を提供します
var g = new Game()
g.levels
/// --> [[1,2,3],[2,3,4],[4,5,6]]
g.levels[0]
/// --> [1,2,3]
dmvaldmanからcritizism取り上げ:書くことは今は不可能である必要があります。 レベル要素に制御されていない書き込み):私はdepracated要素を使用しない(__ defineGetter __)及び2)任意の(つまり書き込みを受け付けていない)1にコードを書き直し。例のセッターが含まれています。
(私は理由値下げのdefineGetter先__間隔を追加する必要がありました)dmvaldmans要求から:
g.levels[0] = [2,3,4];
g.levels;
/// --> [[1,2,3],[2,3,4],[4,5,6]]
//using setter
g.setLevels([g.levels, g.levels, 1,2,3,[9]]);
g.levels;
/// --> [[[1,2,3],[2,3,4],[4,5,6]],[[1,2,3],[2,3,4],[4,5,6]], ....]
//using setLevels
g.setLevels([2,3,4]);
g.levels;
/// --> [2,3,4]
この答えは、プロキシをベースにしたソリューションへの単なる延長です。 その取得のみでプロキシとの溶液が、言及されているが、我々はまた、使用することができます参照してください。 私はここに示していますように設定ます。
お知らせ:セットでの第三引数が値を運ぶことができます...
のコードは自明である。
var _arr = ['one', 'two', 'three'];
var accessCount = 0;
function doSomething() {
accessCount++;
}
var arr = new Proxy(_arr, {
get: function(target, name) {
doSomething();
return target[name];
},
set: function(target, name, val) { doSomething(); target[name] = val; }
});
function print(value) {
document.querySelector('pre').textContent += value + '\n';
}
print(accessCount); // 0
print(arr[0]); // 'one'
print(accessCount); // 1
arr[1] = 10;
print(accessCount); // 2
print(arr[1]); // 10