मैं जावास्क्रिप्ट में [] ऑपरेटर को ओवरलोड करने का तरीका खोजने के लिए प्रतीत नहीं कर सकता। बाहर किसी को पता है?
मैं की तर्ज पर सोच रहा था ...
MyClass.operator.lookup(index)
{
return myArray[index];
}
या मैं सही चीजों को नहीं देख रहा हूं।
मैं जावास्क्रिप्ट में [] ऑपरेटर को ओवरलोड करने का तरीका खोजने के लिए प्रतीत नहीं कर सकता। बाहर किसी को पता है?
मैं की तर्ज पर सोच रहा था ...
MyClass.operator.lookup(index)
{
return myArray[index];
}
या मैं सही चीजों को नहीं देख रहा हूं।
MyClass
वस्तु को एक सरणी बनाएं । आप myArray
अपनी var myObj = new MyClass()
वस्तु से कुंजियों और मूल्यों को कॉपी कर सकते हैं ।
जवाबों:
आप ऑपरेटरों को जावास्क्रिप्ट में अधिभार नहीं दे सकते।
इसे ECMAScript 4 के लिए प्रस्तावित किया गया था लेकिन इसे अस्वीकार कर दिया गया था।
मुझे नहीं लगता कि आप इसे कभी भी देख पाएंगे।
Object arg1: a arg2: b arg3: c
है Object["arg1:arg2:arg3:"](a,b,c)
। तो आपके पास हो सकता है myObject["[]"](1024)
: P
target[name]
में वापस आ सकते हैं , ओपी केवल उदाहरण दिखा रहा है
[]
ऑपरेटर के साथ ही काम करता है , btw:var key = 'world';
console.log(proxy[key]);
इसका सरल उत्तर यह है कि जावास्क्रिप्ट, वर्ग कोष्ठक के माध्यम से किसी वस्तु के बच्चों तक पहुँचने की अनुमति देता है।
तो आप अपनी कक्षा को परिभाषित कर सकते हैं:
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 ) {
...}};
इसके साथ'। तब सेट और मिलता है (भी deleteProperty) कार्यों आग जाएगा। हालाँकि आपको एक प्रॉक्सी ऑब्जेक्ट मिलता है जो कि अधिकांश भाग के लिए अलग-अलग लगता है, तुलना करने के लिए काम करता है (target.constructor === MyClass) यह वर्ग प्रकार आदि है [भले ही यह एक फ़ंक्शन है जहाँ target.constructor.name वर्ग का नाम है पाठ (केवल उन चीजों का एक उदाहरण देख रहा है जो थोड़ा अलग काम करते हैं।)]
तो आप कुछ भी करने की उम्मीद कर रहे हैं जैसे var = MyClassInstance [4]; ? यदि हां, तो सरल उत्तर यह है कि जावास्क्रिप्ट वर्तमान में ऑपरेटर ओवरलोडिंग का समर्थन नहीं करता है।
ऐसा करने का एक आसान तरीका है भाषा का विस्तार करना।
एक कस्टम इंडेक्सिंग कन्वेंशन को परिभाषित करते हैं, चलो इसे "[]" कहते हैं।
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));
एक नया निष्कासन कार्यान्वयन परिभाषित करें। (इस तरह मत करो, लेकिन यह अवधारणा का प्रमाण है)।
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]