2 == [2] জাভাস্ক্রিপ্টে কেন?


164

আমি সম্প্রতি এটি 2 == [2]জাভাস্ক্রিপ্টে আবিষ্কার করেছি । দেখা যাচ্ছে যে, এই ছটফটকের বেশ কয়েকটি আকর্ষণীয় পরিণতি রয়েছে:

var a = [0, 1, 2, 3];
a[[2]] === a[2]; // this is true

একইভাবে, নিম্নলিখিত কাজগুলি:

var a = { "abc" : 1 };
a[["abc"]] === a["abc"]; // this is also true

এমনকি অপরিচিত এখনও, এটি কাজ করে:

[[[[[[[2]]]]]]] == 2; // this is true too! WTF?

এই আচরণগুলি সমস্ত ব্রাউজার জুড়ে সামঞ্জস্যপূর্ণ বলে মনে হয়।

কোনও ভাষা কেন এটি একটি ভাষা বৈশিষ্ট্য?

এখানে এই "বৈশিষ্ট্য" এর আরও উন্মাদ পরিণতি রয়েছে:

[0] == false // true
if ([0]) { /* executes */ } // [0] is both true and false!

var a = [0];
a == a // true
a == !a // also true, WTF?

এই উদাহরণগুলি jimbojw দ্বারা পাওয়া গেছে http://jimbojw.com খ্যাতি সেইসাথে walkingeyerobot

উত্তর:


134

আপনি ইসিএমএ-স্পেসে তুলনা অ্যালগরিদমটি দেখতে পারেন (আপনার সমস্যার জন্য ECMA-262 এর তৃতীয় সংস্করণ: 11.9.3, 9.1, 8.6.2.6)।

আপনি যদি জড়িত বিমূর্ত আলগোরিদিমগুলি জেএস-এ অনুবাদ করেন তবে মূল্যায়ন করার পরে যা ঘটে 2 == [2]তা মূলত এটি:

2 === Number([2].valueOf().toString())

valueOf()অ্যারেগুলির জন্য যেখানে অ্যারে নিজেই ফিরে আসে এবং এক-উপাদান অ্যারের স্ট্রিং-প্রতিনিধিত্ব হ'ল একক উপাদানটির স্ট্রিং প্রতিনিধিত্ব।

এই তৃতীয় উদাহরণটি ব্যাখ্যা হিসাবে [[[[[[[2]]]]]]].toString()এখনও ঠিক স্ট্রিং 2

আপনি দেখতে পাচ্ছেন, দৃশ্যের পিছনে অনেকগুলি জাদু জড়িত রয়েছে, যার কারণেই আমি সাধারণত কেবল কঠোর সমতা অপারেটরটি ব্যবহার করি ===

প্রথম এবং দ্বিতীয় উদাহরণ অনুসরণ করা সহজ কারণ সম্পত্তি নাম সর্বদা স্ট্রিং থাকে তাই so

a[[2]]

সমতুল্য

a[[2].toString()]

যা ঠিক

a["2"]

মনে রাখবেন যে কোনও অ্যারে-ম্যাজিক হওয়ার আগে সংখ্যার কীগুলিও সম্পত্তি নাম হিসাবে (যেমন স্ট্রিং) হিসাবে বিবেচিত হবে।


10

এটি অন্তর্নিহিত ধরণের রূপান্তর কারণে == অপারেটরের ।

[2] সংখ্যার সাথে তুলনা করা হলে সংখ্যা 2 এ রূপান্তরিত হয়। +[2] এ ইউনারি অপারেটরটি ব্যবহার করে দেখুন।

> +[2]
2

অন্যরা বলছেন [2] একটি স্ট্রিতে রূপান্তরিত হয়েছে। +"2"2
নম্বরও

1
আসলে, এটি এত সহজ নয়। [2] স্ট্রিং রূপান্তরিত হয় কাছাকাছি হতে কিন্তু কটাক্ষপাত হবে ecma-international.org/ecma-262/5.1/#sec-11.9.3
নব্য

10
var a = [0, 1, 2, 3];
a[[2]] === a[2]; // this is true

সমীকরণের ডানদিকে, আমাদের কাছে একটি [2] রয়েছে, যা মান 2 দিয়ে একটি সংখ্যা টাইপ করে the অ্যারে এখানে আছে)]। আমি নিশ্চিত নই যে এটি কোনও স্ট্রিং বা একটি সংখ্যার কাছে মূল্যায়ন করে কিনা। 2, বা "2"। প্রথমে স্ট্রিং কেস নিতে দিন। আমি বিশ্বাস করি যে একটি ["2"] একটি নতুন ভেরিয়েবল তৈরি করবে এবং ফিরে আসবে। নাল! == ২. সুতরাং ধরে নেওয়া যাক এটি প্রকৃতপক্ষে সংখ্যায় রূপান্তরিত হচ্ছে। a [2] টাইপ 2 (2) এবং 2 ম্যাচ (সুতরাং === কাজ করে) এবং মান ফিরে আসবে। আমি মনে করি এটি সুস্পষ্টভাবে একটি সংখ্যায় অ্যারে রূপান্তর করছে কারণ একটি [মান] একটি স্ট্রিং বা সংখ্যা আশা করে। দেখে মনে হচ্ছে সংখ্যার চেয়ে বেশি অগ্রাধিকার রয়েছে।

পাশের নোটে, আমি আশ্চর্য হয়েছি যে কে এই প্রাধান্যটি নির্ধারণ করে। [2] এর প্রথম আইটেম হিসাবে একটি সংখ্যা আছে বলেই কি এটি কোনও সংখ্যায় রূপান্তরিত হয়? অথবা এটি হ'ল কোনও অ্যারেকে [অ্যারে] তে পাস করার পরে এটি অ্যারেটিকে প্রথমে একটি সংখ্যায়, তারপরে স্ট্রিংয়ে পরিণত করার চেষ্টা করে। কে জানে?

var a = { "abc" : 1 };
a[["abc"]] === a["abc"];

এই উদাহরণস্বরূপ, আপনি সদস্য হিসাবে একটি শব্দ নামে পরিচিত একটি অবজেক্ট তৈরি করছেন abc। সমীকরণের ডান দিকটি বেশ সহজ; এটি a.abc এর সমতুল্য। এটি ফিরে আসে 1. বাম দিকটি প্রথমে ["abc"] এর একটি আক্ষরিক অ্যারে তৈরি করে। তারপরে আপনি নতুন তৈরি করা অ্যারেতে গিয়ে কোনও বস্তুর উপর একটি ভেরিয়েবল অনুসন্ধান করুন। যেহেতু এটি একটি স্ট্রিং প্রত্যাশা করে, এটি অ্যারেটিকে একটি স্ট্রিংয়ে রূপান্তর করে। এটি এখন একটি ["abc"] এর মূল্যায়ন করে, যা সমান 1 এবং 1 সমান ধরণের (যার কারণেই === কাজ করে) এবং সমান মান।

[[[[[[[2]]]]]]] == 2; 

এটি কেবল একটি অন্তর্নিহিত রূপান্তর। === এই পরিস্থিতিতে কাজ করবে না কারণ এখানে এক ধরণের অমিল রয়েছে।


অগ্রাধিকার সম্পর্কে আপনার প্রশ্নের উত্তর: অ্যারের ==ক্ষেত্রে প্রযোজ্য ToPrimitive()যা ফলস্বরূপ তার toString()পদ্ধতিটি আহ্বান করে , তাই আপনি যা তুলনা করছেন তার 2সাথে স্ট্রিংয়ের সংখ্যাটি "2"; একটি স্ট্রিং এবং একটি সংখ্যার মধ্যে তুলনা স্ট্রিংকে রূপান্তর করে সম্পন্ন করা হয়
ক্রিস্টোফ

8

জন্য ==কেস, এই কেন ডগ Crockford সবসময় ব্যবহার বিশেষ পরামর্শ দেওয়া হচ্ছে ===। এটি কোনও অন্তর্নিহিত ধরণের রূপান্তর করে না।

উদাহরণস্বরূপ উদাহরণস্বরূপ ===, সাম্য অপারেটর বলার আগেই অন্তর্নিহিত ধরণের রূপান্তর সম্পন্ন হয়।


7
[0] == false // true
if ([0]) { /* executes */ } // [0] is both true and false!

এটি আকর্ষণীয়, সত্য যে মিথ্যা [0] উভয়ই সত্য নয় not

[0] == true // false

এটি (জাভাস্ক্রিপ্টের প্রক্রিয়াজাতকরণের মজার উপায় যদি () অপারেটর হয়।


4
আসলে, এটি মজার উপায় ==কাজ করে; আপনি যদি প্রকৃত সুস্পষ্ট কাস্ট ব্যবহার করেন (যেমন Boolean([0])বা !![0]), আপনি দেখতে পাবেন যে এটি বুলিয়ান প্রসঙ্গে যেমন করা উচিত তেমনি [0]মূল্যায়ন করবে true: জেএসে, যে কোনও বিষয় বিবেচনা করা হবেtrue
ক্রিস্টোফ

6

একটি আইটেমের অ্যারেটিকে আইটেম হিসাবেই বিবেচনা করা যেতে পারে।

এটি হাঁসের টাইপিংয়ের কারণে। "2" == 2 == [2] এবং সম্ভবত আরও অনেক কিছু থেকে।


4
কারণ তারা টাইপ করে না। প্রথম উদাহরণে, বাম দিকটি প্রথমে মূল্যায়ন করা হয় এবং তারা মিলের সাথে মিলে যায়।
শান

8
এছাড়াও, আমি মনে করি না হাঁস-টাইপিং এখানে সঠিক শব্দ। ==তুলনা করার আগে অপারেটর দ্বারা সম্পাদিত অন্তর্নিহিত ধরণের রূপান্তরটি করা আরও বেশি ।
চেতন এস

14
এটি হাঁসের টাইপিংয়ের সাথে নয় বরং দুর্বল টাইপিংয়ের সাথে, অর্থাত্ অন্তর্নিহিত ধরণের রূপান্তর
ক্রিস্টোফ

@ চেতান: তিনি যা বলেছিলেন;)
ক্রিস্টোফ

2
চেতান এবং ক্রিস্টোফ যা বলেছিলেন।
টিম ডাউন

3

অন্যান্য উত্তর একটু বিস্তারিত যোগ করতে ... যখন একটি তুলনা Arrayএকটি থেকে Number, জাভাস্ক্রীপ্ট রূপান্তর করবে Arrayসঙ্গে parseFloat(array)। বিভিন্ন Arrayমানগুলি কী রূপান্তরিত হয় তা দেখতে আপনি এটি কনসোলে নিজেই চেষ্টা করতে পারেন (যেমন ফায়ারবগ বা ওয়েব পরিদর্শক) ।

parseFloat([2]); // 2
parseFloat([2, 3]); // 2
parseFloat(['', 2]); // NaN

এর জন্য Array, এর প্রথম সদস্যের সাথে parseFloatঅপারেশন করে Arrayএবং বাকী অংশগুলি ত্যাগ করে।

সম্পাদনা: ক্রিস্টোফের বিশদ বিবরণ অনুসারে, এটি অভ্যন্তরীণভাবে দীর্ঘতর ফর্মটি ব্যবহার করছে এমন হতে পারে তবে ফলাফলগুলি ধারাবাহিকভাবে অভিন্ন হয় parseFloat, সুতরাং parseFloat(array)কীভাবে এটি রূপান্তরিত হবে তা নিশ্চিত হওয়ার জন্য আপনি সর্বদা শর্টহ্যান্ড হিসাবে ব্যবহার করতে পারেন ।


2

আপনি প্রতিটি ক্ষেত্রে 2 টি অবজেক্টের তুলনা করছেন .. ব্যবহার করবেন না ==, আপনি যদি তুলনা করার কথা ভাবছেন তবে আপনার মনে === মনে আছে এবং == নয় not == প্রায়শই উন্মাদ প্রভাব দিতে পারে। ভাষায় ভাল অংশগুলি দেখুন :)


0

প্রশ্নের ইডিটি বিভাগের জন্য ব্যাখ্যা :

1 ম উদাহরণ

[0] == false // true
if ([0]) { /* executes */ } // [0] is both true and false!

ক্রিস্টোফের উত্তর অনুসারে প্রথম টাইপকাস্ট [0] এর কাছে আমাদের কাছে "0" ( [0].valueOf().toString()) রয়েছে

"0" == false

এখন, টাইপকাস্ট বুলিয়ান (মিথ্যা) থেকে সংখ্যা এবং তারপরে স্ট্রিং ("0") থেকে সংখ্যা to

Number("0") == Number(false)
or  0 == 0 
so, [0] == false  // true

ifবিবৃতি হিসাবে , যদি নিজেই শর্তটিতে একটি স্পষ্ট তুলনা না হয় তবে শর্তটি সত্যতার জন্য মূল্যায়ন করে মানগুলির ।

এখানে 6 টি মিথ্যা মান রয়েছে : মিথ্যা, নাল, অপরিজ্ঞাত , 0, ন্যাশনাল খালি স্ট্রিং ""। এবং যে কোনও কিছু মিথ্যা মান নয় এটি সত্যবাদী মান।

[0] যেহেতু মিথ্যা মান নয়, এটি সত্যবাদী মান, ifবিবৃতিটি সত্যকে মূল্যায়ন করে এবং বিবৃতি কার্যকর করে।


দ্বিতীয় উদাহরণ

var a = [0];
a == a // true
a == !a // also true, WTF?

আবার মানগুলিকে আদিমতে কাস্ট করা টাইপ করুন,

    a = a
or  [0].valueOf().toString() == [0].valueOf().toString()
or  "0" == "0" // true; same type, same value


a == !a
or  [0].valueOf().toString() == [0].valueOf().toString()
or  "0" == !"0"
or  "0" == false
or  Number("0") == Number(false)
or  0 = 0   // true
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.