javascriptで[]演算子をオーバーロードする方法が見つからないようです。誰か知ってる?
私は次のことを考えていました...
MyClass.operator.lookup(index)
{
return myArray[index];
}
または私は正しいものを見ていませんか。
javascriptで[]演算子をオーバーロードする方法が見つからないようです。誰か知ってる?
私は次のことを考えていました...
MyClass.operator.lookup(index)
{
return myArray[index];
}
または私は正しいものを見ていませんか。
MyClass
オブジェクトの配列。あなたはからキーと値をコピーすることができmyArray
、あなたのvar myObj = new MyClass()
オブジェクト。
回答:
Object arg1: a arg2: b arg3: c
としてObject["arg1:arg2:arg3:"](a,b,c)
。だからあなたはmyObject["[]"](1024)
:P
target[name]
ゲッターで返すことができる@ Pacerier 、OPは例を示しています
[]
オペレータだけでなく、ところで:var key = 'world';
console.log(proxy[key]);
簡単な答えは、JavaScriptでは角括弧を介してオブジェクトの子にアクセスできるということです。
したがって、クラスを定義できます。
MyClass = function(){
// Set some defaults that belong to the class via dot syntax or array syntax.
this.some_property = 'my value is a string';
this['another_property'] = 'i am also a string';
this[0] = 1;
};
その後、いずれかの構文を使用して、クラスの任意のインスタンスのメンバーにアクセスできるようになります。
foo = new MyClass();
foo.some_property; // Returns 'my value is a string'
foo['some_property']; // Returns 'my value is a string'
foo.another_property; // Returns 'i am also a string'
foo['another_property']; // Also returns 'i am also a string'
foo.0; // Syntax Error
foo[0]; // Returns 1
foo['0']; // Returns 1
foo['random']
、コードが実行できないものをキャッチする方法を求めることです。
プロキシを使用します。それは答えのどこかで言及されましたが、これはより良い例だと思います:
var handler = {
get: function(target, name) {
if (name in target) {
return target[name];
}
if (name == 'length') {
return Infinity;
}
return name * name;
}
};
var p = new Proxy({}, handler);
p[4]; //returns 16, which is the square of 4.
角かっこ演算子は実際にはプロパティアクセス演算子であるため、ゲッターとセッターを使用してフックできます。IEの場合、代わりにObject.defineProperty()を使用する必要があります。例:
var obj = {
get attr() { alert("Getter called!"); return 1; },
set attr(value) { alert("Setter called!"); return value; }
};
obj.attr = 123;
IE8 +についても同じです。
Object.defineProperty("attr", {
get: function() { alert("Getter called!"); return 1; },
set: function(value) { alert("Setter called!"); return value; }
});
IE5-7のonpropertychange
場合、イベントのみがあります。これはDOM要素に対して機能しますが、他のオブジェクトに対しては機能しません。
このメソッドの欠点は、事前定義された名前のない任意のプロパティではなく、事前定義されたプロパティのセットへのリクエストのみをフックできることです。
obj['any_key'] = 123;
が、コードに表示されているものは、(まだ知られていない)キーのセッター/ゲッターを定義する必要があります。それは不可能。
説明されているようにプロキシを使用する必要がありますが、最終的にはクラスコンストラクタに統合できます
return new Proxy(this, {
set: function( target, name, value ) {
...}};
これとともに'。次に、set関数とget(またdeleteProperty)関数が起動します。異なるように見えるProxyオブジェクトを取得しますが、ほとんどの場合、比較を要求するように機能します(target.constructor === MyClass)。クラスタイプなどです。[target.constructor.nameがクラス名である関数ですがテキスト(わずかに異なる動作の例に注意してください。)]
したがって、var what = MyClassInstance [4]のようなことをしたいと思っています。?もしそうなら、簡単な答えは、Javascriptは現在演算子のオーバーロードをサポートしていないということです。
これを行うための卑劣な方法の1つは、言語自体を拡張することです。
カスタムインデックス付け規則を定義し、それを「[]」と呼びましょう。
var MyClass = function MyClass(n) {
this.myArray = Array.from(Array(n).keys()).map(a => 0);
};
Object.defineProperty(MyClass.prototype, "[]", {
value: function(index) {
return this.myArray[index];
}
});
...
var foo = new MyClass(1024);
console.log(foo["[]"](0));
新しいeval実装を定義します。(このようにしないでください。ただし、これは概念実証です)。
var MyClass = function MyClass(length, defaultValue) {
this.myArray = Array.from(Array(length).keys()).map(a => defaultValue);
};
Object.defineProperty(MyClass.prototype, "[]", {
value: function(index) {
return this.myArray[index];
}
});
var foo = new MyClass(1024, 1337);
console.log(foo["[]"](0));
var mini_eval = function(program) {
var esprima = require("esprima");
var tokens = esprima.tokenize(program);
if (tokens.length == 4) {
var types = tokens.map(a => a.type);
var values = tokens.map(a => a.value);
if (types.join(';').match(/Identifier;Punctuator;[^;]+;Punctuator/)) {
if (values[1] == '[' && values[3] == ']') {
var target = eval(values[0]);
var i = eval(values[2]);
// higher priority than []
if (target.hasOwnProperty('[]')) {
return target['[]'](i);
} else {
return target[i];
}
return eval(values[0])();
} else {
return undefined;
}
} else {
return undefined;
}
} else {
return undefined;
}
};
mini_eval("foo[33]");
上記は、より複雑なインデックスでは機能しませんが、より強力な解析で機能する可能性があります。
独自のスーパーセット言語を作成する代わりに、既存の言語に表記をコンパイルしてから評価することができます。これにより、初めて使用した後の解析オーバーヘッドがネイティブに削減されます。
var compile = function(program) {
var esprima = require("esprima");
var tokens = esprima.tokenize(program);
if (tokens.length == 4) {
var types = tokens.map(a => a.type);
var values = tokens.map(a => a.value);
if (types.join(';').match(/Identifier;Punctuator;[^;]+;Punctuator/)) {
if (values[1] == '[' && values[3] == ']') {
var target = values[0];
var i = values[2];
// higher priority than []
return `
(${target}['[]'])
? ${target}['[]'](${i})
: ${target}[${i}]`
} else {
return 'undefined';
}
} else {
return 'undefined';
}
} else {
return 'undefined';
}
};
var result = compile("foo[0]");
console.log(result);
console.log(eval(result));
プロキシ取得できます| セットするメソッドを直接ます。これに触発されました。
class Foo {
constructor(v) {
this.data = v
return new Proxy(this, {
get: (obj, key) => {
if (typeof(key) === 'string' && (Number.isInteger(Number(key)))) // key is an index
return obj.data[key]
else
return obj[key]
},
set: (obj, key, value) => {
if (typeof(key) === 'string' && (Number.isInteger(Number(key)))) // key is an index
return obj.data[key] = value
else
return obj[key] = value
}
})
}
}
var foo = new Foo([])
foo.data = [0, 0, 0]
foo[0] = 1
console.log(foo[0]) // 1
console.log(foo.data) // [1, 0, 0]