জাভাস্ক্রিপ্ট: অপারেটর ওভারলোডিং


95

আমি এখন জাভাস্ক্রিপ্টের সাথে কয়েক দিন ধরে কাজ করছি এবং এমন একটি জায়গায় পৌঁছেছি যেখানে আমি আমার সংজ্ঞায়িত অবজেক্টগুলির জন্য অপারেটরদের ওভারলোড করতে চাই।

গুগল অনুসন্ধানের পরে এটি অনুসন্ধান করার পরে মনে হচ্ছে আপনি আনুষ্ঠানিকভাবে এটি করতে পারবেন না, তবুও কিছু লোক আছেন যারা এই ক্রিয়াটি সম্পাদন করার জন্য কিছুটা দীর্ঘ-দাবী করার দাবি করছেন।

মূলত আমি একটি ভেক্টর 2 ক্লাস করেছি এবং নিম্নলিখিতগুলি করতে সক্ষম হতে চাই:

var x = new Vector2(10,10);
var y = new Vector2(10,10);

x += y; //This does not result in x being a vector with 20,20 as its x & y values.

পরিবর্তে আমি এটি করতে হচ্ছে:

var x = new Vector2(10,10);
var y = new Vector2(10,10);

x = x.add(y); //This results in x being a vector with 20,20 as its x & y values. 

আমার ভেক্টর 2 ক্লাসে ওভারলোড অপারেটরগুলির কাছে কি আমি নিতে পারি? এটি যেমন সরল কদর্য দেখায়।



4
সবেমাত্র একটি অপারেটর ওভারলোডিং লাইব্রেরি জুড়ে এসেছিল। এটি চেষ্টা করেন নি এবং এটি কতটা ভাল কাজ করে তা জানেন না, যদিও: google.com/…
ফিশিনিয়ার

উত্তর:


105

যেমন আপনি খুঁজে পেয়েছেন, জাভাস্ক্রিপ্ট অপারেটর ওভারলোডিং সমর্থন করে না। আপনি যে নিকটে আসতে পারেন তা হ'ল বাস্তবায়ন করা toString(যা ডাকে যখন স্ট্রিং হিসাবে জোর করা দরকার তখন ডাকা হবে) এবং valueOf(যা এটি সংখ্যার কাছে জোর করে ডাকতে হবে, উদাহরণস্বরূপ +সংযোজনের জন্য ব্যবহার করার সময় , বা অনেক ক্ষেত্রে যখন এটি কনক্যাটেনেশনের জন্য ব্যবহার করা হচ্ছে কারণ সংক্ষিপ্তকরণের +আগে সংযোজন করার চেষ্টা করে), যা বেশ সীমাবদ্ধ। Vector2ফলস্বরূপ আপনাকে কোনও বস্তু তৈরি করতে দেয় না ।


এই প্রশ্নে আসা লোকদের জন্য যারা ফলাফল হিসাবে একটি স্ট্রিং বা সংখ্যা চান (ক এর পরিবর্তে Vector2), যদিও, এর উদাহরণ valueOfএবং এখানে toString। এই উদাহরণগুলি অপারেটর ওভারলোডিং প্রদর্শন করে না , কেবল জাভাস্ক্রিপ্টের অন্তর্নির্মিত হ্যান্ডলিংটি আদিম রূপান্তরিত করার সুবিধা গ্রহণ করে:

valueOf

এই উদাহরণটি কোনও valআদিমকে জোর করে জবাব দেওয়ার জন্য কোনও বস্তুর সম্পত্তির মান দ্বিগুণ করে , উদাহরণস্বরূপ +:

অথবা ES2015 এর সাথে class:

বা কেবল অবজেক্টস সহ, কোনও নির্মাণকারী নেই:

toString

এই উদাহরণটি কোনও valআদিমকে জোর করে জবাব দেওয়ার ক্ষেত্রে কোনও বস্তুর সম্পত্তির মানকে আপার ক্ষেত্রে রূপান্তরিত করে , উদাহরণস্বরূপ +:

অথবা ES2015 এর সাথে class:

বা কেবল অবজেক্টস সহ, কোনও নির্মাণকারী নেই:


4
যদিও এটি জেএসের যথাযথভাবে সমর্থিত নয়, আজকাল কাস্টম বৈশিষ্ট্যগুলি সহ জেএস প্রসারিত করা এবং সাধারণ জেএসে ফিরে ট্রান্সিলিপ করা খুব সাধারণ,
দিমিত্রি জইতসেভ

4
Dateক্লাসে তুলনা করা অপারেটরগুলি কি স্পষ্টভাবে ব্যবহার করে তারিখগুলি সংখ্যায় রূপান্তর করে valueOf? উদাহরণস্বরূপ আপনি করতে পারেন date2 > date1এবং এটি সত্য যদি date2পরে তৈরি করা হয় date1
শান লেতেড্রে

4
@ সানলিটেন্ড্রে: হ্যাঁ >, <, >=, এবং <=(কিন্তু ==, ===, !=, অথবা !==) ব্যবহার সারাংশ রিলেশনাল তুলনা অপারেশন, যা ব্যবহারের ToPrimitiveইঙ্গিত "সংখ্যা" সঙ্গে। একটি Dateঅবজেক্টে, এর ফলে ফলাফলটি getTimeফিরে আসে (মিলি সেকেন্ডস-দ্য-এপোচ মান)।
টিজে ক্রাউডার

24

যেমন টিজে বলেছে, আপনি জাভাস্ক্রিপ্টে অপারেটরদের ওভারলোড করতে পারবেন না। তবে আপনি valueOfহ্যাক লিখতে ফাংশনটির সুবিধা নিতে পারেন যা addপ্রতিবারের মতো ফাংশন ব্যবহারের চেয়ে ভাল বলে মনে হয় , তবে এক্স এবং y 0 এবং MAX_VALUE এর মধ্যে থাকা সীমাবদ্ধতাগুলি ভেক্টরের উপর চাপিয়ে দেয়। কোডটি এখানে:

var MAX_VALUE = 1000000;

var Vector = function(a, b) {
    var self = this;
    //initialize the vector based on parameters
    if (typeof(b) == "undefined") {
        //if the b value is not passed in, assume a is the hash of a vector
        self.y = a % MAX_VALUE;
        self.x = (a - self.y) / MAX_VALUE;
    } else {
        //if b value is passed in, assume the x and the y coordinates are the constructors
        self.x = a;
        self.y = b;
    }

    //return a hash of the vector
    this.valueOf = function() {
        return self.x * MAX_VALUE + self.y;
    };
};

var V = function(a, b) {
    return new Vector(a, b);
};

তারপরে আপনি এই জাতীয় সমীকরণ লিখতে পারেন:

var a = V(1, 2);            //a -> [1, 2]
var b = V(2, 4);            //b -> [2, 4]
var c = V((2 * a + b) / 2); //c -> [2, 4]

7
আপনি ওপির addপদ্ধতির জন্য মূলত কোডটি লিখেছেন ... কিছু তারা করতে চায় নি।
আয়ান ব্রিন্ডলি

16
@ আইয়ানব্রিন্ডলি ওপি অপারেটরকে ওভারলোড করতে চেয়েছিল, যা স্পষ্টভাবে ইঙ্গিত দেয় যে তিনি এই জাতীয় কোনও ফাংশন লেখার পরিকল্পনা করেছিলেন। ওপির উদ্বেগ ছিল "অ্যাড", যা অপ্রাকৃত কল; গাণিতিকভাবে, আমরা একটি +চিহ্ন সহ ভেক্টর সংযোজনকে উপস্থাপন করি । এটি একটি খুব ভাল উত্তর যা অর্ধ-সংখ্যাসূচক বস্তুর জন্য অপ্রাকৃত ফাংশন নামটি এড়াতে পারে তা দেখায়।
কিটসিল

4
@ কিটসিল প্রশ্নটি দেখায় যে আমি ইতিমধ্যে একটি অ্যাড ফাংশন ব্যবহার করছি। যদিও উপরের ফাংশনটি মোটেও খারাপ ফাংশন নয় এটি প্রশ্নের সমাধান করে না, তাই আমি আয়ানের সাথে একমত হতে চাই।
লি ব্রিনডলে

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

নোট করুন যে দুটি ভেক্টরকে গুণিত করার সময় এটি একটি অপ্রত্যাশিত ফলাফল (ত্রুটি দেওয়ার পরিবর্তে) ফেরত দেবে। স্থানাঙ্কগুলি অবশ্যই পূর্ণসংখ্যার হতে হবে।
ব্যবহারকারী 202729

8

এফওয়াইআই পেপার.জেএস ভ্যাক্টরগুলির অপারেটর ওভারলোডিং সহ একটি স্বয়ংসম্পূর্ণ, স্কোপড জাভাস্ক্রিপ্ট তৈরি করে পেপারস্ক্রিপ্ট তৈরি করে এই সমস্যাটি সমাধান করে, যা এটি পরে জাভাস্ক্রিপ্টে ফিরে প্রক্রিয়াকরণ করে।

তবে কাগজপত্রের ফাইলগুলি নির্দিষ্টভাবে নির্দিষ্ট এবং প্রক্রিয়াজাত করা দরকার।


8

আসলে, জাভাস্ক্রিপ্টের একটি বৈকল্পিক রয়েছে যা অপারেটর ওভারলোডিং সমর্থন করে । ফটোডপ এবং ইলাস্ট্রেটারের মতো অ্যাডোব অ্যাপ্লিকেশনগুলির দ্বারা ব্যবহৃত স্ক্রিপ্টিং ভাষা এক্সটেনডস্ক্রিপ্টের অপারেটর ওভারলোডিং রয়েছে। এটিতে, আপনি লিখতে পারেন:

Vector2.prototype["+"] = function( b )
{
  return new Vector2( this.x + b.x, this.y + b.y );
}

var a = new Vector2(1,1);
var b = new Vector2(2,2);
var c = a + b;

এটি "অ্যাডোব এক্সটেন্ডসস্ক্রিপ্ট জাভাস্ক্রিপ্ট সরঞ্জাম গাইড" (বর্তমান লিঙ্কটি এখানে ) এ আরও বিশদে বর্ণনা করা হয়েছে । বাক্য গঠনটি স্পষ্টতই ECMAScript স্ট্যান্ডার্ডের (এখন দীর্ঘ পরিত্যক্ত) খসড়ার ভিত্তিতে তৈরি হয়েছিল।


11
এক্সটেনডস্ক্রিপ্ট! = জাভাস্ক্রিপ্ট
Andrio Skur

4
পেপারস্ক্রিপ্ট উত্তরটি উর্ধ্বলিত করার সময় কেন এক্সটেনডস্ক্রিপ্ট উত্তরটি নিম্নচালিত হয়? এই উত্তরটিও ভাল IM
xmedeko

5

দুটিতে একটিতে প্যাক করা ভেক্টর গণিত করা সম্ভব It's এটি কীভাবে কাজ করে তা বর্ণনা করার আগে আমাকে প্রথমে একটি উদাহরণ দেখান:

let a = vec_pack([2,4]);
let b = vec_pack([1,2]);

let c = a+b; // Vector addition
let d = c-b; // Vector subtraction
let e = d*2; // Scalar multiplication
let f = e/2; // Scalar division

console.log(vec_unpack(c)); // [3, 6]
console.log(vec_unpack(d)); // [2, 4]
console.log(vec_unpack(e)); // [4, 8]
console.log(vec_unpack(f)); // [2, 4]

if(a === f) console.log("Equality works");
if(a > b) console.log("Y value takes priority");

আমি এই সত্যটি ব্যবহার করছি যে আপনি যদি দুটি সংখ্যার এক্স বার বার শিফট করেন এবং তারপরে তাদের স্থানান্তরিত করার আগে এগুলি যুক্ত বা বিয়োগ করেন তবে আপনি একই ফলাফল পাবেন যেন আপনি তাদের শুরুতে স্থানান্তরিত করেননি। একইভাবে স্কেলার গুণ এবং বিভাগ স্থানান্তরিত মানগুলির জন্য প্রতিসমভাবে কাজ করে।

একটি জাভাস্ক্রিপ্ট নম্বরে পূর্ণসংখ্যার নির্ভুলতার 52 বিট রয়েছে (64 বিট ফ্লোট), তাই আমি একটি সংখ্যাকে তিনি উচ্চতর উপলব্ধ 26 বিটগুলিতে প্যাক করব এবং একটি নিম্নের মধ্যে রাখব। কোডটি কিছুটা আরও অগোছালো হয়ে গেছে কারণ আমি স্বাক্ষরিত সংখ্যাগুলিকে সমর্থন করতে চেয়েছিলাম।

function vec_pack(vec){
    return vec[1] * 67108864 + (vec[0] < 0 ? 33554432 | vec[0] : vec[0]);
}

function vec_unpack(number){
    switch(((number & 33554432) !== 0) * 1 + (number < 0) * 2){
        case(0):
            return [(number % 33554432),Math.trunc(number / 67108864)];
        break;
        case(1):
            return [(number % 33554432)-33554432,Math.trunc(number / 67108864)+1];
        break;
        case(2):
            return [(((number+33554432) % 33554432) + 33554432) % 33554432,Math.round(number / 67108864)];
        break;
        case(3):
            return [(number % 33554432),Math.trunc(number / 67108864)];
        break;
    }
}

এর সাথে আমি দেখতে পাচ্ছি যে এক্স এবং ওয়াইটি + -৩৩ মিলিয়ন পরিসরে থাকতে হবে, যেহেতু তাদের প্রতিটি বিট ২ 26 বিটের মধ্যে ফিট করতে হয়।


ভেক_প্যাকের সংজ্ঞা কোথায়?
12:16

4
@ ডিসগাস্টিং হুঁ দুঃখিত, দেখে মনে হচ্ছে আমি এটি যুক্ত করতে ভুলে গিয়েছিলাম ... এটি এখন ঠিক হয়ে গেছে :)
স্টাফ

4

প্রশ্নের সঠিক উত্তর না থাকলেও ইএস 6 সিম্বলস ব্যবহার করে অজগর __magic__ পদ্ধতিতে কিছু বাস্তবায়ন সম্ভব

একটি [Symbol.toPrimitive]()পদ্ধতি আপনাকে কল বোঝাতে দেয় না Vector.add(), তবে আপনাকে সিনট্যাক্স ব্যবহার করতে দেয় Decimal() + int

class AnswerToLifeAndUniverseAndEverything {
    [Symbol.toPrimitive](hint) {
        if (hint === 'string') {
            return 'Like, 42, man';
        } else if (hint === 'number') {
            return 42;
        } else {
            // when pushed, most classes (except Date)
            // default to returning a number primitive
            return 42;
        }
    }
}

3

আমরা valueOfপ্রতিটি পুনরাবৃত্তির পদ্ধতি থেকে ভিন্ন মান সহ তীর ফাংশনটি মূল্যায়নের জন্য প্রতিক্রিয়াযুক্ত হুক ব্যবহার করতে পারি ।

const a = Vector2(1, 2) // [1, 2]
const b = Vector2(2, 4) // [2, 4]    
const c = Vector2(() => (2 * a + b) / 2) // [2, 4]
// There arrow function will iterate twice
// 1 iteration: method valueOf return X component
// 2 iteration: method valueOf return Y component

লাইব্রেরি @ জেএস-বেসিক / ভেক্টর ভেক্টর 3 এর জন্য একই ধারণাটি ব্যবহার করে।



1

আমি একটি লাইব্রেরি লিখেছি যা কাঁচা জেএসে এটি করার জন্য একগুচ্ছ দুষ্ট হ্যাকের ব্যবহার করে। এটি এগুলির মত প্রকাশের অনুমতি দেয়।

  • জটিল সংখ্যা:

    >> Complex()({r: 2, i: 0} / {r: 1, i: 1} + {r: -3, i: 2}))

    <- {r: -2, i: 1}

  • স্বয়ংক্রিয় পার্থক্য:

    যাক f(x) = x^3 - 5x:

    >> var f = x => Dual()(x * x * x - {x:5, dx:0} * x);

    এখন কিছু মান ধরে এটি মানচিত্র:

    >> [-2,-1,0,1,2].map(a=>({x:a,dx:1})).map(f).map(a=>a.dx)

    <- [ 7, -2, -5, -2, 7 ]

    অর্থাত্ f'(x) = 3x^2 - 5.

  • বহুবচন:

    >> Poly()([1,-2,3,-4]*[5,-6]).map((c,p)=>''+c+'x^'+p).join(' + ')

    <- "5x^0 + -16x^1 + 27x^2 + -38x^3 + 24x^4"

আপনার নির্দিষ্ট সমস্যার জন্য, আপনি Vector2লাইব্রেরি ব্যবহার করে কোনও ফাংশন (বা আরও কিছু সংক্ষিপ্ত কিছু) সংজ্ঞায়িত করবেন , তারপরে লিখবেনx = Vector2()(x + y);

https://gist.github.com/pyrocto/5a068100abd5ff6dfbe69a73bbc510d7

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