Learn JavaScript

lesson ৪ / ৯ · type, operator আর coercion: '5' + 2 কেন 7 না

Module ২ · type, operator আর coercion: '5' + 2 কেন 7 না

== কখন, কখন না, আর বাকি judgement call-গুলো

Freeপড়া

এই lesson-এ যা শিখবে

  • Default হিসেবে === বেছে নিতে পারবে, আর null আর undefined একসাথে ধরতে লিখতে পারবে x == null, একমাত্র == যেটা সবাই মেনে নেয়।
  • Number() আর parseInt, ?? আর ||, toFixed আর সাধারণ number, === আর Object.is: প্রতিটা জোড়া থেকে বেছে নিতে পারবে, কারণসহ।
  • ==, === আর Object.is-এর বারো জোড়ার chart পড়তে পারবে, আর বুঝিয়ে বলতে পারবে বেশিরভাগ team কেন ===-এর নিয়মটা একটা linter-এর হাতে ছেড়ে দেয়।

Amara Kenji-কে একটা pull request পাঠায়, মানে দোকানের code-এ একটা বদল, review-এর জন্য। if (discount == null) লাইনে Kenji একটাই comment লেখে: "never use =="। Amara-র লাইনটা ঠিক ছিল, আবার Kenji-র নিয়মটাও ভালো। দুটোই সত্যি হতে পারে, কারণ ভালো একটা default মানেই আইন না। এই lesson আগে নিয়মটার পেছনের chart-টা আঁকে, তারপর পাঁচটা judgement call নেয়, প্রতিটার জন্য একটা করে program।

"সমান?" জিজ্ঞেস করার তিন উপায়

JavaScript-এ সমান কিনা দেখার উপায় তিনটা। ===, মানে strict equality, true হয় যখন দুই দিকের type এক আর value-ও এক, কোনো convert ছাড়াই। ==, মানে loose equality, type আলাদা হলে আগে convert করে, lesson 01 আর 02-এ দেখা নিয়মে। Object.is(a, b) এসেছে ES2015-এ, কাজ করে ===-এর মতোই, শুধু দুইটা ব্যতিক্রম বাদে। এই module বারবার যে বারো জোড়ায় ফিরে আসে, তিনটা check সেগুলোর উপর এখানে।

==, === আর Object.is দিয়ে বারো জোড়ার তুলনা বারো জোড়া, "সমান?" জিজ্ঞেস করার তিন উপায় # x y x == y x === y Object.is(x, y) 1 1 "1" true false false 2 0 "" true false false 3 0 "0" true false false 4 "" "0" false false false 5 null undefined true false false 6 null 0 false false false 7 undefined 0 false false false 8 NaN NaN false false true 9 0 -0 true true false 10 true 1 true false false 11 true "true" false false false 12 false "0" true false false বাক্সে ঘেরা true মানে true। == আর === আলাদা হয় সারি 1, 2, 3, 5, 10 আর 12-তে, যেখানে type আলাদা। Object.is === থেকে আলাদা শুধু সারি 8 আর 9-এ: NaN, আর দুই রকম শূন্য। সারি 2, 3 আর 4: 0 == "" আর 0 == "0" দুটোই true, অথচ "" == "0" false।

এর চারটা সারি তুমি নিজেই run করে দেখতে পারো। row এক লাইনের একটা arrow function, যেটা এক জোড়ার তিনটা উত্তর print করে।

const out = [];
const row = (label, x, y) => out.push(label + ": " + (x == y) + " " + (x === y) + " " + Object.is(x, y));

row("1 and \"1\"", 1, "1");
row("null and undefined", null, undefined);
row("NaN and NaN", NaN, NaN);
row("0 and -0", 0, -0);

console.log(out.join("\n"));
1 and "1": true false false
null and undefined: true false false
NaN and NaN: false false true
0 and -0: true true false

Chart-টা পড়া

প্রথম দুইটা ফলের কলাম দিয়ে শুরু করো। ছয়টা সারিতে == আর ===-এর মত মেলে না, আর প্রতিটাতেই দুই দিকের type আলাদা, তাই == convert করেছে। Type এক হলে standard বলে দিয়েছে, == হুবহু ===-এর কাজটাই করবে।

এবার সারি 2, 3 আর 4। 0 == "" true, 0 == "0"-ও true, অথচ "" == "0" false। সারি 4-এর দুই দিকই string, তাই কিছুই convert হয় না, আর দুইটা আলাদা text সমান না। মানে == transitive না: a যদি b-র সমান হয় আর b যদি c-র সমান হয়, তাতে a আর c সমান হয়ে যায় না। একে এড়ানোর আসল কারণ এটাই, speed-ও না, style-ও না।

সারি 5, 6 আর 7-এ আছে ব্যতিক্রমটা। ==-এর হিসাবে null আর undefined শুধু একে অন্যের সমান, আর কারও না, 0-এরও না। সারি 8 আর 9 হলো একমাত্র জায়গা, যেখানে Object.is আর === আলাদা পথে যায়। তাই === কখনো চমকে দেয় না, আর == চমকে দেয় ঠিক সেই সারিগুলোতে, যেগুলো তুমি মুখস্থ করোনি।

এই lesson-এর নতুন দুইটা check

value == null
Object.is(a, b)
  • value == null true হয় যখন value হলো null বা undefined, আর বাকি সব value-র জন্য false।
  • Object.is(a, b) কাজ করে a === b-এর মতো, শুধু NaN সমান NaN-এর, আর 0 সমান না -0-এর।

x == null, একমাত্র == যেটা লেখার মতো

একটা value দুইভাবে না থাকতে পারে। undefined মানে কেউ সেটা set-ই করেনি, যেমন object-এ কখনো না থাকা একটা property। null মানে কেউ ইচ্ছে করে খালি করে রেখেছে। Setting পড়ার code সাধারণত দুটোকেই "নেই" ধরতে চায়, আর কিছুকে না।

Example 1: কোন check কী ধরে

"এটা কি নেই?" জিজ্ঞেস করার তিনটা উপায়, ছয়টা value-র উপর, যাদের সবাইকেই খালি খালি লাগে।

const out = [];
const row = (label, value) => out.push(label + ": == null " + (value == null) + ", === null " + (value === null) + ", !value " + !value);

row("null", null);
row("undefined", undefined);
row("0", 0);
row("empty string", "");
row("false", false);
row("NaN", NaN);

console.log(out.join("\n"));
null: == null true, === null true, !value true
undefined: == null true, === null false, !value true
0: == null false, === null false, !value true
empty string: == null false, === null false, !value true
false: == null false, === null false, !value true
NaN: == null false, === null false, !value true

== null ঠিক দুইটা না-থাকা value-ই ধরে। === null undefined-কে ফসকে যায়। !value ছয়টাই ধরে, তাই 0-এর discount-ও "নেই" হয়ে যেত। Amara-র discount == null-ই ছিল একদম মাপমতো check। লম্বা রূপটা, discount === null || discount === undefined, একই কথা বলে; যে team-এর নিয়মে সব == নিষেধ, তারা এটাই লেখে।

Run in Compiler

বেশিরভাগ team সিদ্ধান্তটা linter-কে দেয়, আর সেটাই ঠিক

Linter এমন একটা program, যেটা তোমার code পড়ে ঝুঁকির জায়গাগুলো দাগিয়ে দেয়; Module 1-এ নাম এসেছিল ESLint-এর, JavaScript-এর একটা linter। এর eqeqeq নিয়মটা প্রতিটা == আর !=-কে দাগায়। { "null": "ignore" } option দিলে == null ছাড় পায়, আর "smart" option-ও এটাকে ছাড় দেয়। Airbnb-র style guide হুবহু এই setting-টাই দেয়:

module.exports = [
  {
    rules: {
      eqeqeq: ["error", "always", { null: "ignore" }],
    },
  },
];

এটা একটা ESLint configuration file, eslint.config.js। এটা কিছু print করে না, তাই এর কোনো output নেই। jQuery-র style guide-ও কথায় একই কথা বলে: সবসময় ===, একমাত্র ব্যতিক্রম null দিয়ে null আর undefined একসাথে check করা।

সিদ্ধান্তটা একটা নিয়মের হাতে ছেড়ে দেওয়া ঠিক আছে, review comment-এর চেয়ে বরং ভালো। কাউকে chart মনে রাখতে হয় না, আর review-তে operator নিয়ে না, design নিয়ে তর্ক হয়। Airbnb-র মতো করে সাজানো থাকলে linter Amara-র লাইনটা পাস করিয়ে দিত, Kenji-কে আর comment লিখতে হতো না।

পুরো string-এর জন্য Number, সামনের অংশের জন্য parseInt

Lesson 03-এ দুই রকম পাঠক দেখেছ: Number() চায় পুরো text, parseInt পড়ে সামনের অংশ। কোনটা নেবে, সেটা নির্ভর করে text-টার কী হওয়ার কথা তার উপর। এই module-এর সব converter নিচের flowchart-এ এক পাতায়।

কোন converter: সিদ্ধান্তের flowchart এই value থেকে তোমার কী চাই? Text থেকে একটা number। পুরো text-টাই কি number? হ্যাঁ Number(text) তারপর NaN বাতিল আর খালি text-ও না, শুধু সামনে Number আছে সামনের দিকে (12px, 3.5kg)। শুধু পূর্ণসংখ্যা? হ্যাঁ parseInt(text, 10) না parseFloat(text) মানুষকে দেখানোর text? toFixed(digits) নির্দিষ্ট দশমিকের জন্য Intl.NumberFormat ভাগ আর মুদ্রার জন্য true নাকি false? Boolean(value) যেকোনো value-র text? String(value) সাজানো ফেরত দেয় text, তাই সেটা সবসময় শেষ ধাপ: আগে হিসাব করো। Number("") হলো 0, তাই Number()-এর উপর ভরসার আগে খালি text check করো।
Example 2: একটা পরিমাণ, একটা চওড়া, একটা version

পাঁচটা text, প্রতিটা দুইভাবে পড়া। দোকানের form-এর পরিমাণ (quantity) শুরু থেকে শেষ পর্যন্ত number হতেই হবে; একটা চওড়া বা একটা version নম্বর শুধু number দিয়ে শুরু হয়।

const out = [];
const both = (label, text) => out.push(label + " " + text + ": Number " + Number(text) + ", parseInt " + parseInt(text, 10));

both("quantity", "12");
both("quantity", "2O");
both("quantity", "");
both("width", "250px");
both("version", "22.16.0");

console.log(out.join("\n"));
quantity 12: Number 12, parseInt 12
quantity 2O: Number NaN, parseInt 2
quantity : Number 0, parseInt NaN
width 250px: Number NaN, parseInt 250
version 22.16.0: Number NaN, parseInt 22

"2O"-তে একজন customer শূন্যের জায়গায় ইংরেজি O টাইপ করেছে। parseInt চুপচাপ 2টা বাক্স order করে ফেলে; Number বলে NaN, তখন form আবার জিজ্ঞেস করতে পারে। খালি field দেখায় Number-এর একমাত্র ফাঁদ, 0, যেটা নিয়ে flowchart-এর প্রথম বাক্সটাই সাবধান করে। চওড়া আর version-এ সামনের number-টাই আসল কথা, তাই সেখানে parseInt ঠিক।

Run in Compiler

0 আর খালি text যখন আসল উত্তর, তখন ??

Lesson 02 দেখিয়েছে, || যেকোনো falsy value পেলেই default-এ চলে যায়, আর ?? যায় শুধু null আর undefined-এ। সিদ্ধান্তটা আসলে data-র ব্যাপার। এখানে 0 কি আসল একটা উত্তর, আর ""?

Example 3: যে setting-গুলো ইচ্ছে করে save করা

Bob ওর music player mute করে রেখেছে, তাই save করা volume হলো 0। গানের নামগুলোর মাঝে ও কোনো separator চায়নি, তাই সেটা ""। Theme ও কখনো বেছেই নেয়নি।

const out = [];
const saved = { volume: 0, separator: "", theme: undefined };

out.push("volume with ||: " + (saved.volume || 50));
out.push("volume with ??: " + (saved.volume ?? 50));
out.push("separator with ||: [" + (saved.separator || ", ") + "]");
out.push("separator with ??: [" + (saved.separator ?? ", ") + "]");
out.push("theme with ??: " + (saved.theme ?? "light"));

console.log(out.join("\n"));
volume with ||: 50
volume with ??: 0
separator with ||: [, ]
separator with ??: []
theme with ??: light

|| দিলে Bob-এর mute করা player চালু হয় volume 50-এ, আর separator না চাওয়ার সিদ্ধান্তটা উপেক্ষিত হয়। ?? দুটোই রেখে দেয়, আর যে theme ও কখনো set করেনি, সেটা ঠিকই বসিয়ে দেয়। || ঠিক তখন, যখন খালি মানেই সত্যিই "দেওয়া হয়নি", যেমন একটা খালি display name, যেখানে "Guest" দেখানো উচিত।

Run in Compiler

toFixed দেখানোর জন্য, হিসাবের জন্য কখনো না

Lesson 03 বলেছিল: আগে হিসাব, শেষে text। এবার এমন একটা bill, যেখানে শুধু ক্রম ঠিক রাখলেও চলে না। 48.50-এর 15 শতাংশ হলো 7.275, আর total 55.775। দুটোই শেষ হয় 5-এ, আর toFixed গোল করে store করা binary value-টাকে, যেটা আসল সংখ্যার চুল পরিমাণ উপরে বা নিচে বসে থাকে।

Example 4: এক cent ভুল একটা রসিদ

একই tip দুইবার হিসাব করা: একবার দশমিকে, একবার পুরো cent-এ। Math.round সবচেয়ে কাছের পূর্ণসংখ্যায় গোল করে।

const out = [];
const bill = 48.5;
const percent = 15;

const tip = bill * percent / 100;
out.push("in decimals: tip " + tip.toFixed(2) + ", total " + (bill + tip).toFixed(2));

const billCents = Math.round(bill * 100);
const tipCents = Math.round(billCents * percent / 100);
const totalCents = billCents + tipCents;
out.push("in cents:    tip " + (tipCents / 100).toFixed(2) + ", total " + (totalCents / 100).toFixed(2));

console.log(out.join("\n"));
in decimals: tip 7.28, total 55.77
in cents:    tip 7.28, total 55.78

প্রথম রসিদ বলছে 48.50 যোগ 7.28 হলো 55.77। Store করা 7.275 আসলে 7.2750000000000003..., তাই উপরের দিকে গোল হয়; আর 55.775 আসলে 55.774999999999998..., তাই নিচের দিকে। Cent-এ 4850 গুণ 15 ভাগ 100 হুবহু 727.5, গোল হয়ে 728, আর পূর্ণসংখ্যা যোগ হয় একদম নিখুঁত। তাই একবার গোল করে পুরো cent-এ নাও, পূর্ণসংখ্যা যোগ করো, আর toFixed call করো শুধু print করার সময়।

Run in Compiler

NaN আর -0-এর জন্য Object.is

=== দুইটা জায়গায় জেনেশুনেই ভুল বলে, standard এভাবেই বানিয়েছে। NaN === NaN false, lesson 01-এ Zara-র সেই test। 0 === -0 true, অথচ -0 একটা আসল value, যেটা screen-এ এসে হাজির হতে পারে।

Example 5: হারানো একটা reading আর একটা negative শূন্য

একটা আবহাওয়া station একটা reading-এর জায়গায় পাঠায় "n/a", আর -0.4-এর একটা তাপমাত্রা দেখানোর জন্য গোল করা হয়।

const out = [];
const reading = Number("n/a");

out.push("reading === NaN: " + (reading === NaN));
out.push("Number.isNaN(reading): " + Number.isNaN(reading));
out.push("Object.is(reading, NaN): " + Object.is(reading, NaN));

const rounded = Math.round(-0.4);
out.push("rounded: " + rounded);
out.push("rounded === 0: " + (rounded === 0));
out.push("Object.is(rounded, -0): " + Object.is(rounded, -0));
out.push("(-0.4).toFixed(0): " + (-0.4).toFixed(0));

console.log(out.join("\n"));
reading === NaN: false
Number.isNaN(reading): true
Object.is(reading, NaN): true
rounded: 0
rounded === 0: true
Object.is(rounded, -0): true
(-0.4).toFixed(0): -0

=== NaN কখনো কোনো NaN খুঁজে পায় না; রোজকার check হলো Number.isNaN, আর Object.is-ও একমত। Math.round(-0.4) হলো -0: print হয় 0 হিসেবে, === 0-ও পাস করে, কিন্তু toFixed দেখায় "-0", আবহাওয়ার app-এর সেই "-0 ডিগ্রি"। দুই রকম শূন্যকে আলাদা করতে পারে একমাত্র Object.is। এটা তোমার কালেভদ্রে লাগবে, তাতে কোনো সমস্যা নেই।

Run in Compiler

এটা কোথায় কাজে লাগে

  • ESLint। eqeqeq নিয়মের নিজের page এটা বোঝায় [] == false, [] == ![] আর 3 == "03" দিয়ে, তিনটাই true, আর "smart" আর null: "ignore" option-গুলোর কথা লিখে রাখে।
  • Airbnb JavaScript Style Guide। ওদের ESLint configuration eqeqeq-কে set করে "always", সাথে null: "ignore", তাই x == null পাস করে আর বাকি সব == আটকে যায়।
  • TypeScript। Compiler == নিষেধ করে না। একটা number-এর সাথে একটা string-এর তুলনা দেখলে, == হোক বা ===, সে error TS2367 দেয়: "This comparison appears to be unintentional because the types 'number' and 'string' have no overlap."
  • React। একটা component-এর state set করলে React নতুন value-টাকে পুরনোটার সাথে Object.is দিয়ে মেলায়, আর দুটো একই হলে আবার render করা বাদ দেয়।

যে ভুলগুলো সবাই করে

১. Kenji-র fix: যে value undefined হতে পারে, তার উপর === null।

const order = { price: 200 };
const discount = order.discount;
const final = discount === null ? order.price : order.price * (1 - discount);
console.log("final: " + final);
final: NaN

কোনো error নেই। Order-এ কখনো discount ছিলই না, তাই সেটা undefined, null না, আর 200 * (1 - undefined) হলো NaN। লেখো discount == null। এই বদলটা তুমি করবে, কারণ "never use ==" শুনলে মনে হয় এর কোনো ব্যতিক্রম নেই।

২. === দিয়ে NaN খোঁজা।

const score = Number("ten");
console.log(score === NaN ? "bad input" : "score " + score);
score NaN

এই check কখনো true হতে পারে না, কারণ ===-এর হিসাবে NaN কারও সমান না, নিজেরও না। লেখো Number.isNaN(score)। তুমি === NaN লিখবে, কারণ পড়তে একদম সোজা ইংরেজির মতো লাগে।

৩. "নেই" বোঝাতে ! ব্যবহার করা।

const quantity = 0;
console.log(!quantity ? "missing" : "quantity " + quantity);
missing

পরিমাণ 0 দেওয়া হয়েছিল, অথচ program বলছে নেই, কারণ 0 falsy। "নেই" বোঝাতে চাইলে লেখো quantity == null। তুমি !-এর দিকে হাত বাড়াবে, কারণ এটা ছোট, আর যে value-গুলো দিয়ে test করেছিলে সবগুলোতেই কাজ করেছে।

মাথা খাটাও

console.log("abc" < "abd");
console.log("Z" < "a");

দুইটা লাইনই print করে true। এটা থেকে < দুইটা string-কে কীভাবে মেলায়, সে সম্পর্কে কী বোঝা যায়? Run করার আগে আন্দাজ করো "apple" < "Banana" কী দেবে।

দুইটা string এক ঘর এক ঘর করে মেলাও, অভিধান যেভাবে মেলায়। তারপর ভাবো, computer প্রতিটা অক্ষরের জন্য কোন সংখ্যা রাখে, আর বড় হাতের অক্ষর আগে আসে কিনা।

অনুশীলন ১সহজ

Maria chart-এর প্রতিটা সারি নিজের screen-এ দেখতে চায়, lesson যে চারটা চালিয়েছে শুধু সেগুলো না। এই program সারি 1 print করে। Chart-এর ক্রমে সারি 2 থেকে 12 যোগ করো, চালাও, আর প্রতিটা লাইন chart-এর সাথে মিলিয়ে দেখো।

const out = [];
const row = (label, x, y) => out.push(label + ": " + (x == y) + " " + (x === y) + " " + Object.is(x, y));

row("1 and \"1\"", 1, "1");
// add rows 2 to 12 of the chart here, in the chart's order

console.log(out.join("\n"));

আলাদা করে grade হয় না। নিচের কঠিন অনুশীলন three-equalities একই বারোটা সারি grade করে, typed input থেকে।

Run in Compiler
অনুশীলন ২মাঝারি

David-এর form প্রতি লাইনে একটা করে field পাঠায়। না-থাকা field, খালি field আর সত্যিকারের 0, তিনটাকে ওর আলাদা করতে হবে, যেগুলো || এক বস্তায় ভরে ফেলত।

Input. এক লাইনে n, তারপর n-টা লাইন। প্রতিটা লাইন এভাবে পড়ো: হুবহু null মানে null, হুবহু undefined মানে undefined, খালি লাইন মানে "", তা না হলে Number(line), যদি সেটা NaN না হয়, আর তাও না হলে text-টাই।

Output. প্রতিটা value-র জন্য এক লাইন: value == null হলে missing, === "" হলে empty, === 0 হলে zero, আর বাকি সব ক্ষেত্রে value, একটা space, তারপর String(value)।

Constraints. 1 <= n <= 20000। প্রতিটা লাইনে 0 থেকে 20টা অক্ষর, দুই মাথায় কোনো space নেই, আর শেষ লাইনটা কখনো খালি না।

Sample. Input 6, তারপর null, একটা খালি লাইন, 0, undefined, 42 আর abc দিলে ছয় লাইনে missing, empty, zero, missing, value 42 আর value abc।

const input = require("fs").readFileSync(0, "utf8");
const lines = input.split("\n");
let at = 0;
const next = () => lines[at++];
const nextInt = () => Number(next());
const out = [];

// your code: read with next() and nextInt(), push every line of output to out

console.log(out.join("\n"));

missing-empty-zero নামে grade হয়। এটা starter-এর lines variant, তাই next() পুরো একটা লাইন ফেরত দেয়, খালি লাইনও। দুই রকম না-থাকা value-র জন্য একটাই == null check ব্যবহার করো।

Run in Compiler
অনুশীলন ৩কঠিন

যে chart Zara নিজে run করেনি, তাতে ওর ভরসা নেই। ও প্রতিটা জোড়া typed token হিসেবে লেখে, আর প্রতিটার তিনটা উত্তর চায়।

Input. এক লাইনে n, তারপর n-টা লাইনে x y। প্রতিটা token-এর একটা type আছে: num:-এর পরে text মানে Number(text), তাই num:NaN, num:-0 আর num:Infinity-ও চলবে। str:-এর পরে text মানে ওই string, আর শুধু str: মানে ""। বাকি token-গুলো bool:true, bool:false, null আর undefined।

Output. প্রতিটা জোড়ার জন্য এক লাইনে তিনটা শব্দ: x == y, x === y আর Object.is(x, y), যেমন true false false।

Constraints. 1 <= n <= 20000। প্রতিটা token-এ বড়জোর 25টা অক্ষর, ভিতরে কোনো space নেই, আর num:-এর পরের text কখনো খালি না।

Sample. Input 4, তারপর চার লাইনে num:1 str:1, null undefined, num:NaN num:NaN আর num:0 str: দিলে true false false, true false false, false false true আর true false false।

const input = require("fs").readFileSync(0, "utf8");
const tokens = input.split(/\s+/).filter(Boolean);
let at = 0;
const next = () => tokens[at++];
const nextInt = () => Number(next());
const out = [];

// your code: read with next() and nextInt(), push every line of output to out

console.log(out.join("\n"));

three-equalities নামে grade হয়। t.slice(4) একটা token-এর প্রথম চারটা character বাদ দিয়ে বাকিটা দেয়, তাই "num:-0".slice(4) হলো "-0"; এটা শেখাবে Module 3। Hidden test-এ chart-এর বারোটা জোড়াই আছে, আরও আছে।

Run in Compiler

সচরাচর যে প্রশ্নগুলো আসে

  • == null যদি ঠিক থাকে, তাহলে যেখানে == ঠিক উত্তর দেয়, সেখানেই ব্যবহার করি না কেন?

    কারণ তখন প্রতিবার chart-টা মনে রাখতে হবে, তোমাকেও, পরের পাঠককেও। সারি 4 দেখিয়েছে == transitive-ও না। == null একমাত্র case যেটা মনে রাখার মতো ছোট: দুইটা value, আর কিছু না।

  • === কি ==-এর চেয়ে fast?

    Kenji এটা জিজ্ঞেস করে, আর প্রশ্নটাই ভুল। দুই দিকের type এক হলে standard ==-কে হুবহু === হিসেবেই সংজ্ঞায়িত করেছে। এই lesson কিছুই মাপেনি, তাই বেছে নাও মানে দেখে, speed দেখে না।

  • ===-এর বদলে সব জায়গায় Object.is লিখব?

    না। এটা আলাদা শুধু NaN আর দুই রকম শূন্যের বেলায়, আর পাঠক আশা করে === দেখবে। NaN-এর জন্য Number.isNaN ব্যবহার করো, আর Object.is রাখো সেই বিরল code-এর জন্য, যাকে 0 আর -0 আলাদা করতে হয়।

  • TypeScript কি আমাকে == লিখতে দেয় না?

    দেয়। দুইটা type-এর মধ্যে কোনো মিল থাকা সম্ভব না হলে সে TS2367 দেয়, তুমি যে operator-ই লেখো। কোন operator চলবে, সেটা ঠিক করা linter-এর কাজ, eqeqeq দিয়ে।

মূল কথা

  • Default হলো ===: এক type, এক value, কোনো convert নেই, কোনো table মনে রাখার দরকার নেই।
  • x == null একমাত্র == যেটা সবাই মেনে নেয়: এটা null আর undefined ধরে, আর কিছু না, আর linter একে ছাড় দিতে পারে।
  • যে value-কে শুরু থেকে শেষ পুরোটা number হতে হবে, তার জন্য Number(); সামনে থাকা number-এর জন্য parseInt(text, 10) বা parseFloat।
  • 0 আর "" যখন আসল উত্তর, তখন ??; যখন প্রতিটা falsy value মানেই "দেওয়া হয়নি", তখন ||।
  • টাকা রাখো পুরো cent-এ, আর toFixed call করো শুধু print করার সময়; Object.is হলো NaN আর -0-এর জন্য।
  • আরও গভীরে: Under the Hood, abstract equality algorithm আর floating point (Pro)।

এরপর lesson 05 engine-এর ভিতরটা খোলে, আর chart-এর প্রতিটা == সারির পেছনের algorithm-টা এক ধাপ এক ধাপ করে হেঁটে দেখায়।

lesson ৪ শেষ

শেষ হলে চিহ্ন দিন, অগ্রগতি আপনার সাথে থাকবে।

পরেরটা: ভেতরের কথা: abstract equality algorithm আর floating point

== কখন, কখন না, আর বাকি judgement call-গুলো | Learn JavaScript | Progsity