আপনি কীভাবে জাভাস্ক্রিপ্টে [] অপারেটরটি ওভারলোড করবেন


86

আমি জাভাস্ক্রিপ্টে [] অপারেটরটিকে ওভারলোড করার উপায় খুঁজে পাচ্ছি না। বাইরে কেউ জানেন?

আমি চিন্তা করেছিলাম ...

MyClass.operator.lookup(index)
{
     return myArray[index];
}

বা আমি সঠিক জিনিসগুলির দিকে তাকাচ্ছি না


4
এখানে উত্তর ভুল, জাতীয় ক্ষেত্রে বিন্যাসগুলির শুধু বস্তু যার চাবি uint32 করার coercable হয় (- 1) মূল্যবোধ ও তাদের প্রোটোটাইপ অতিরিক্ত পদ্ধতি আছে
বেঞ্জামিন Gruenbaum

কেবল আপনার MyClassবস্তুকে একটি অ্যারে করুন। আপনি কী এবং মানগুলি myArrayআপনার var myObj = new MyClass()অবজেক্টে অনুলিপি করতে পারেন ।
jpaugh

আরে, আমি ওভারলোড চাই}} অপারেটর, কোনও ধারণা?
ড্যানিয়েল অ্যাসায়েগ

উত্তর:


81

আপনি জাভাস্ক্রিপ্টে অপারেটরগুলি ওভারলোড করতে পারবেন না।

এটি ECMAScript 4 এর জন্য প্রস্তাব করা হয়েছিল তবে তা প্রত্যাখ্যান করা হয়েছে।

আমি মনে করি না আপনি তাড়াতাড়ি যে কোনও সময় দেখতে পাবেন।


4
এটি ইতিমধ্যে কিছু ব্রাউজারের প্রক্সিগুলির সাথে করণীয়যোগ্য হতে পারে এবং কোনও সময়ে সমস্ত ব্রাউজারে আসবে। Github.com/DavidBruant/ProxyArray
ত্রিস্তান

তারপরে আপনি [] বা .eq () ব্যবহার করেন কিনা তার উপর নির্ভর করে jQuery কীভাবে বিভিন্ন জিনিস ফিরিয়ে দেয়? stackoverflow.com/a/6993901/829305
রিক্কি

4
আপনি এখনই প্রক্সি দিয়ে এটি করতে পারেন।
আইয়াল

যদিও আপনি সেগুলিতে চিহ্নগুলির সাহায্যে পদ্ধতিগুলি সংজ্ঞায়িত করতে পারবেন যতক্ষণ না আপনি "" না দিয়ে অ্যারে হিসাবে অ্যাক্সেস করেন। এইভাবে স্মলটক ভালো জিনিস মানচিত্র এর Object arg1: a arg2: b arg3: cহিসাবে Object["arg1:arg2:arg3:"](a,b,c)। সুতরাং আপনি থাকতে পারেন myObject["[]"](1024): পি
দিমিত্রি

লিঙ্কটি মারা গেছে :(
Gp2mv3

71

আপনি এটি ES6 প্রক্সি দিয়ে করতে পারেন ( সমস্ত আধুনিক ব্রাউজারে উপলব্ধ)

var handler = {
    get: function(target, name) {
        return "Hello, " + name;
    }
};
var proxy = new Proxy({}, handler);

console.log(proxy.world); // output: Hello, world

বিশদ বিবরণ চেক MDN


4
একটি সূচক অ্যাক্সেসর দিয়ে আমরা কীভাবে আমাদের নিজস্ব ক্লাস তৈরি করতে এটি ব্যবহার করব? অর্থাৎ আমি নিজের কনস্ট্রাক্টরটি ব্যবহার করতে চাই, আমি প্রক্সি তৈরি করতে চাই না।
এমপেন

4
এটি সত্য ওভারলোডিং নয়। বস্তুটিতে নিজে কল করার পদ্ধতিগুলির পরিবর্তে আপনি এখন প্রক্সিটির পদ্ধতিগুলি কল করছেন।
পেসারিয়ার

@ পেসারিয়র আপনি গিটারে ফিরে আসতে পারেন target[name], ওপি কেবল উদাহরণগুলি দেখিয়েছে
ভ্যালেন

4
সঙ্গে কাজ করে []পাশাপাশি অপারেটর, BTW:var key = 'world'; console.log(proxy[key]);
Klesun

15

সহজ উত্তরটি হল জাভাস্ক্রিপ্ট স্কয়ার বন্ধনীগুলির মাধ্যমে কোনও অবজেক্টের শিশুদের অ্যাক্সেসের অনুমতি দেয়।

সুতরাং আপনি আপনার শ্রেণি সংজ্ঞায়িত করতে পারেন:

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

4
আমি অবশ্যই পারফরম্যান্সের কারণে এটির জন্য সুপারিশ করব না, তবে এটি এখানে সমস্যার একমাত্র আসল সমাধান। সম্ভবত একটি সম্পাদন উল্লেখ করে যে এটি সম্ভব নয় এটি এটিকে দুর্দান্ত উত্তর দেবে।
মিলিমেট্রিক

4
এই নয় কি প্রশ্ন চায়। প্রশ্নটি foo['random']আপনার কোডটি করতে সক্ষম নয় যা ধরার জন্য একটি উপায় জিজ্ঞাসা করছে ।
পেসারিয়ার

9

একটি প্রক্সি ব্যবহার করুন। উত্তরে এটি অন্য কোথাও উল্লেখ করা হয়েছিল তবে আমি মনে করি এটি একটি আরও ভাল উদাহরণ:

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.

সম্ভবত উল্লেখ করার মতো যে প্রক্সিগুলি একটি ES6 বৈশিষ্ট্য এবং অতএব আরও সীমিত ব্রাউজার সমর্থন রয়েছে (এবং বাবেল সেগুলি নকলও করতে পারে না )।
jdehesa

8

ব্র্যাকেট অপারেটর প্রকৃতপক্ষে সম্পত্তি অ্যাক্সেস অপারেটর হিসাবে, আপনি গেটর এবং সেটটারগুলির সাহায্যে এটি আঁকতে পারেন। আই-এর জন্য আপনাকে তার পরিবর্তে অবজেক্ট.ডেফাইনপোপার্টি () ব্যবহার করতে হবে। উদাহরণ:

var obj = {
    get attr() { alert("Getter called!"); return 1; },
    set attr(value) { alert("Setter called!"); return value; }
};

obj.attr = 123;

আইই 8 + এর জন্য একই:

Object.defineProperty("attr", {
    get: function() { alert("Getter called!"); return 1; },
    set: function(value) { alert("Setter called!"); return value; }
});

আইআই 5-7 এর জন্য onpropertychangeকেবল ইভেন্ট রয়েছে, যা ডিওএম উপাদানগুলির জন্য কাজ করে, তবে অন্যান্য বস্তুর জন্য নয়।

পদ্ধতির অপূর্ণতা হ'ল আপনি কেবল পূর্বনির্ধারিত বৈশিষ্ট্যের সেটগুলির অনুরোধগুলিতে ঝুঁকতে পারেন, কোনও পূর্বনির্ধারিত নাম ব্যতীত স্বেচ্ছাসেবী সম্পত্তিতে নয়।


আপনি দয়া করে jsfiddle.net আপনার পদ্ধতির ডেমো করতে পারেন ? আমি ধরে নিলাম যে সমাধানটি কী কী এক্সপ্রেশন হিসাবে কাজ করতে হবে obj['any_key'] = 123;তবে আমি আপনার কোডে যা দেখছি তার জন্য কোনও (এখনও জানা যায়নি) কীটির জন্য আমাকে সেটার / গেটর সংজ্ঞায়িত করতে হবে। যে অসম্ভব.
dma_k

4
আরও 1 বিয়োগফল অফসেট 1 কারণ এটি কেবল আইই নয়।
বৃত্তাকার

এটি কোনও শ্রেণির ফাংশনের জন্য করা যেতে পারে? আমি নিজে থেকে সিনট্যাক্সটি খুঁজতে লড়াই করছি।
মাইকেল হফম্যান

7

যেমন ব্যাখ্যা করেছেন আপনি এখানে প্রক্সি ব্যবহার করতে হবে, কিন্তু এটা শেষ পর্যন্ত একটি বর্গ একত্রিত করা যেতে পারে কন্সট্রাকটর

return new Proxy(this, {
    set: function( target, name, value ) {
...}};

এর সাথে'. তারপরে সেট অ্যান্ড গেট (ডিলিটপ্রোপার্টি) ফাংশনগুলিতে আগুন লাগবে। যদিও আপনি একটি প্রক্সি অবজেক্ট পেয়েছেন যা বেশিরভাগ অংশের তুলনায় এটির চেয়ে পৃথক বলে মনে হয় (টার্গেট.constructor === মাই ক্লাস) এটি শ্রেণীর ধরণের ইত্যাদি [[যদিও এটি এমন একটি ফাংশন যেখানে টার্গেট.constructor.name শ্রেণীর নাম পাঠ্য (কিছুটা পৃথকভাবে কাজ করে এমন উদাহরণগুলির উল্লেখ করা ing)


4
এটি ব্যাকবোন সংগ্রহের উপর [] ওভারলোড করার জন্য ভাল কাজ করে যাতে পৃথক মডেল অবজেক্টগুলি [] ব্যবহার করে অন্য সমস্ত বৈশিষ্ট্যের জন্য একটি পাস-মাধ্যমে ব্যবহার করে ফিরে আসে।
justkt

5

সুতরাং আপনি আশা করছেন ভেরার মতো কিছু করুন = MyClassInstance [4]; ? যদি তা হয় তবে সরল উত্তরটি হ'ল জাভাস্ক্রিপ্ট বর্তমানে অপারেটর ওভারলোডিং সমর্থন করে না।


4
কিভাবে jQuery কাজ করে। আপনি jQuery অবজেক্টে method ('। Foo')। এইচটিএমএল () এর মতো কোনও মেথড কল করতে পারেন বা matching ('। Foo') এর মতো প্রথম মেলানো ডোম উপাদান পেতে পারেন [0]
কাগনিক

4
jQuery একটি ফাংশন, আপনি $ ফাংশনে একটি প্যারামিটার দিয়ে যাচ্ছেন। সুতরাং () বন্ধনীগুলি [] নয়
জেমস ওয়েস্টগেট

5

এটির জন্য একটি স্পিচী উপায় হ'ল ভাষা নিজেই প্রসারিত করা।

ধাপ 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));

4
আপনি
কুঁকড়ে

4
একেবারে জঘন্য আমি এটা ভালোবাসি.
SliceThePi

চতুরতা সাধারণত এক উপায় বা অন্যভাবে হয়। এর অর্থ এই নয় যে এটি কোনও উপযুক্ত অনুশীলন নয় যা পর্যাপ্ত সংস্থান দিয়ে অর্থ প্রদান করতে পারে। সবচেয়ে অলস ব্যক্তিরা হ'ল তারা তাদের নিজস্ব সংকলক এবং অনুবাদক লেখেন যাতে তারা উপলব্ধ না থাকলেও তারা আরও পরিচিত পরিবেশে কাজ করতে পারে। এটি বলেছিল, এটি এলাকায় আরও অভিজ্ঞতার সাথে কেউ যদি খুব তাড়াহুড়োয় কম লিখেছিল তবে এটি কম বিরক্তিকর হবে। সমস্ত অনানুষ্ঠানিক সমাধানগুলি একরকম বা অন্যভাবে ঘৃণ্য, আমাদের কাজ হ'ল ট্রেডফসগুলি জেনে এবং পরিণতিগুলির সাথে লড়াই করা।
দিমিত্রি

3

আমরা প্রক্সি পেতে পারি | সরাসরি পদ্ধতি সেট করুন । দ্বারা অনুপ্রাণিত এই

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]
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.