Javascript'te [] operatörünü aşırı yüklemenin bir yolunu bulamıyorum. Orada bilen var mı?
Düşünüyordum da ...
MyClass.operator.lookup(index)
{
return myArray[index];
}
yoksa doğru şeylere bakmıyor muyum?
Javascript'te [] operatörünü aşırı yüklemenin bir yolunu bulamıyorum. Orada bilen var mı?
Düşünüyordum da ...
MyClass.operator.lookup(index)
{
return myArray[index];
}
yoksa doğru şeylere bakmıyor muyum?
MyClass
nesnenizi bir dizi yapın. Sen anahtarlarını ve değerlerini kopyalayabilirsiniz myArray
sizin için var myObj = new MyClass()
nesne.
Yanıtlar:
JavaScript'te operatörleri aşırı yükleyemezsiniz.
Bu edilmiş ECMAScript'e 4 için önerilen ancak reddedildi.
Yakında göreceğini sanmıyorum.
Object arg1: a arg2: b arg3: c
olduğu Object["arg1:arg2:arg3:"](a,b,c)
. Yani sahip olabilirsiniz myObject["[]"](1024)
: P
target[name]
, OP sadece örnekleri gösteriyor
[]
Operatörle de çalışır , btw:var key = 'world';
console.log(proxy[key]);
Basit cevap, JavaScript'in köşeli parantezler aracılığıyla bir Nesnenin alt öğelerine erişime izin vermesidir.
Böylece sınıfınızı tanımlayabilirsiniz:
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;
};
Daha sonra her iki sözdizimiyle sınıfınızın herhangi bir örneğindeki üyelere erişebileceksiniz.
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']
kodunuzun yapamayacağı bir şeyi yakalamanın bir yolunu soruyor .
Bir vekil kullanın. Cevaplarda başka bir yerde bahsedilmişti ama bence bu daha iyi bir örnek:
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.
Parantez operatörü aslında mülk erişim operatörü olduğundan, alıcılar ve ayarlayıcılarla ona bağlanabilirsiniz. IE için bunun yerine Object.defineProperty () kullanmanız gerekecektir. Misal:
var obj = {
get attr() { alert("Getter called!"); return 1; },
set attr(value) { alert("Setter called!"); return value; }
};
obj.attr = 123;
IE8 + için aynı:
Object.defineProperty("attr", {
get: function() { alert("Getter called!"); return 1; },
set: function(value) { alert("Setter called!"); return value; }
});
IE5-7 için onpropertychange
yalnızca DOM öğeleri için çalışan, ancak diğer nesneler için geçerli olmayan olay vardır .
Yöntemin dezavantajı, önceden tanımlanmış herhangi bir adı olmayan rastgele özelliğe değil, yalnızca önceden tanımlanmış özellik kümesine olan isteklere bağlanabilmenizdir.
obj['any_key'] = 123;
ancak kodunuzda gördüğüm şey herhangi bir (henüz bilinmeyen) anahtar için ayarlayıcı / alıcı tanımlamam gerekiyor. İmkansız.
Proxy'yi açıklandığı gibi kullanmanız gerekir, ancak sonuçta bir sınıf yapıcısına entegre edilebilir
return new Proxy(this, {
set: function( target, name, value ) {
...}};
Bununla'. Daha sonra set ve get (ayrıca deleteProperty) işlevleri etkinleşir. Farklı görünen bir Proxy nesnesi elde etseniz de, çoğu zaman karşılaştırmayı sormak işe yarar (target.constructor === MyClass) sınıf türü vb. [Target.constructor.name'nin sınıf adı olduğu bir işlev olmasına rağmen metin (sadece biraz farklı çalışan şeylere bir örnek olarak)]
Yani var ne olursa olsun = Sınıfım [4] gibi bir şey yapmayı umuyorsunuz; ? Öyleyse, basit cevap, Javascript'in şu anda operatör aşırı yüklemesini desteklememesidir.
Bunu yapmanın sinsi bir yolu, dilin kendisini genişletmektir.
özel bir indeksleme kuralı tanımlayın, buna "[]" diyelim.
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));
yeni bir eval uygulaması tanımlar. (bunu bu şekilde yapmayın, ancak bu bir kavram kanıtıdır).
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]");
yukarıdakiler daha karmaşık dizinler için işe yaramayacaktır, ancak daha güçlü ayrıştırma ile olabilir.
Kendi üst küme dilinizi oluşturmak yerine, notasyonunuzu mevcut dile göre derleyebilir ve sonra değerlendirebilirsiniz. Bu, ilk kullanımdan sonra ayrıştırma ek yükünü yerel olarak azaltır.
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));
Vekil alabiliriz | yöntemleri doğrudan ayarlayın . Esinlenen bu .
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]