ویرگول
ورودثبت نام
Hedieh
Hediehفرانت‌اند دولوپر | کد تمیز، طراحی دقیق
Hedieh
Hedieh
خواندن ۵ دقیقه·۲ ماه پیش

فصل ۷ – Dynamic Typing

جاوااسکریپت یه زبان dynamically typed هست — یعنی متغیرها به نوع خاصی محدود نیستن. این یه قدرت بزرگه، ولی همزمان یه منبع بزرگ باگ هم هست. مثلاً:

const possiblyNumeric = '203.45'; function setWidth(width) { width += 20; // انتظار داریم عدد بشه 223.45 applyWidth(width); } setWidth(possiblyNumeric); // => '203.4520' ← رشته!

چون یه operand رشته‌ست، + به‌جای جمع، concatenate می‌کنه. همین یه خط ساده منشأ میلیون‌ها ساعت debugging در دنیا بوده.

این فصل دو موضوع اصلی رو پوشش می‌ده: تشخیص تایپ و تبدیل تایپ.


تشخیص تایپ (Detection)

قبل از اینکه بریم سراغ تکنیک‌ها، یه سوال مهم: واقعاً چی رو می‌خوایم تشخیص بدیم؟

اغلب فکر می‌کنیم باید تایپ دقیق رو چک کنیم، ولی این می‌تونه کد رو بی‌دلیل rigid کنه. مثلاً این تابع:

function registerPeopleForMarathon(people) { if (Array.isArray(people)) { throw new Error('People is not an array'); } for (let person of people) { if (!(person instanceof Person)) { throw new Error('Each person should be an instance of Person'); } registerForMarathon(person.id, person.name); } }

این چک‌ها بیشتر از اینکه کمک کنن، محدودیت می‌سازن. for...of روی هر iterable کار می‌کنه — نه فقط آرایه. و برای person هم، مهم اینه که id و name داشته باشه، نه اینکه حتماً instance از Person باشه.

رویکرد بهتر — duck typing:

function isIterable(obj) { return obj != null && typeof obj[Symbol.iterator] === 'function'; } function registerPeopleForMarathon(people) { if (!isIterable(people)) { throw new Error('People is not iterable'); } for (let person of people) { if (!person || !person.name || !person.id) { throw new Error('Each person should have a name and id'); } registerForMarathon(person.id, person.name); } }

اگه مثل اردک راه میره و مثل اردک قار قار می‌کنه، اردکه — لازم نیست شناسنامه‌اش رو ببینیم.


typeof

اولین ابزار تشخیص تایپ، typeof هست:

typeof 1; // => "number" typeof ''; // => "string" typeof {}; // => "object" typeof function(){}; // => "function" typeof undefined; // => "undefined" typeof Symbol(); // => "symbol" typeof 0n; // => "bigint" typeof true; // => "boolean"

ولی typeof یه دوست ناپایداره — دو تله بزرگ داره:

اول اینکه typeof null برابر "object" برمی‌گردونه — یه باگ تاریخی که هرگز درست نشده.

دوم اینکه بین انواع مختلف object فرق نمی‌ذاره:

typeof []; // => "object" typeof RegExp(''); // => "object" typeof {};

تشخیص تایپ‌های مختلف

Boolean: معمولاً کافیه مستقیم توی شرط استفاده بشه. اگه می‌خواید مطمئن باشید دقیقاً true یا false هست:

if (isEnabled === true) {...}

Number: typeof درست کار می‌کنه، ولی NaN و Infinity هم "number" برمی‌گردونن. برای چک کردن عدد معتبر:

function isNormalNumber(n) { return typeof n === 'number' && isFinite(n); }

تفاوت isNaN و Number.isNaN رو هم بدونید:

isNaN('foo'); // => true (اول cast می‌کنه) Number.isNaN('foo'); // => false (بدون cast)

String: ساده‌ترین تشخیص رو داره:

typeof 'hello'; // => "string"

برای چک کردن اینکه رشته غیرخالیه:

function isNonEmptyString(string) { return typeof string === 'string' && string.trim().length > 0; }

undefined: بهترین راه استفاده از typeof:

if (typeof value === 'undefined') {...}

یا از void 0 به‌عنوان جایگزین مطمئن:

if (value === void 0) {...}

null: باید مستقیم چک بشه:

if (someValue === null) {...}

null یا undefined با هم: صریح‌ترین راه:

if (value === null || value === undefined) {...}

یه راه کوتاه‌تر هم هست که محبوبه، ولی ممکنه نیت رو مبهم کنه:

if (value == null) {...} // هر دو null و undefined رو می‌گیره

Array: از Array.isArray استفاده کنید:

if (Array.isArray(value)) {...}

ولی اگه فقط می‌خواید روش loop بزنید، بهتره iterable بودنش رو چک کنید.

Plain Object: با بررسی [[Prototype]]:

function isPlainObject(object) { return Object.getPrototypeOf(object) === Object.prototype; }

تبدیل تایپ: Casting و Coercion

دو نوع تبدیل تایپ داریم:

Casting — عمدی و صریح:
javascript

Number('123'); // => 123 String(456); // => "456"

Coercion — ضمنی و خودکار توسط جاوااسکریپت:

1 + '123'; // => "1123" (رشته!) [2] * [3]; // => 6 (عدد!) '22' / 2; // => 11 (عدد!)

coercion چون ضمنیه، می‌تونه منشأ باگ‌های عجیب بشه. همیشه به تایپ operand‌هاتون مطمئن باشید.


تبدیل به Boolean

همه مقادیر به Boolean قابل تبدیلن — مگه هفت مقدار falsy.

دو روش صریح:

Boolean(0); // => false Boolean(1); // => true !!0; // => false !!1; // => true

double-bang (!!) یه روش رایجه که ارزش یه مقدار رو به Boolean تبدیل می‌کنه. مفیده وقتی می‌خواید مطمئن بشید تابعتون همیشه Boolean برمی‌گردونه:

function isNamePopulated(name) { return !!name; } isNamePopulated(''); // => false isNamePopulated(null); // => false isNamePopulated('Sandra'); // => true

تبدیل به String

صریح‌ترین روش، String() هست:

String(456); // => "456" String(true); // => "true" String(null); // => "null" String([1, 2, 3]); // => "1,2,3"

دو روش کوتاه‌تر هم وجود داره، ولی تفاوت ظریفی دارن:

'' + 1234; // => "1234" (از valueOf استفاده می‌کنه) `${1234}`; // => "1234" (مستقیم toString رو صدا می‌زنه)

این تفاوت وقتی آبجکت شما هم valueOf و هم toString داره، می‌تونه نتایج متفاوت بده. پس همیشه از String() استفاده کنید.


تبدیل به Number

صریح‌ترین روش، Number() هست:

Number('10e3'); // => 10000 Number(' 4.6'); // => 4.6 Number('wat'); // => NaN Number(false); // => 0

روش کوتاه‌تر: unary +:

+'55.66'; // => 55.66 +'foo'; // => NaN

parseInt و parseFloat هم وجود دارن ولی با احتیاط باید ازشون استفاده کرد:

parseInt('100', 8); // => 64 (octal) parseFloat('42.01'); // => 42.01

parseInt radix رو همیشه صریح بدید — وگرنه ممکنه خودش تصمیم بگیره و نتایج غیرمنتظره بگیرید.


ToPrimitive

وقتی جاوااسکریپت می‌خواد یه آبجکت رو به primitive تبدیل کنه، این ترتیب رو دنبال می‌کنه:

۱. اگه [Symbol.toPrimitive] داره، ازش استفاده می‌کنه
۲. اگه نه، valueOf رو امتحان می‌کنه
۳. اگه نه، toString رو صدا می‌زنه

const one = { [Symbol.toPrimitive]: () => 1, valueOf: () => 2, toString: () => 3 }; const two = { valueOf: () => 2, toString: () => 3 }; const three = { toString: () => 3 }; 1 == one; // => true 2 == two; // => true 3 == three; // => true

جمع‌بندی

dynamic typing جاوااسکریپت یه شمشیر دولبه‌ست. اگه بدونید چطور تشخیص بدید و تبدیل کنید، می‌تونید کد انعطاف‌پذیر و قابل اعتماد بنویسید. اگه ندونید، همون یه خط += می‌تونه ساعت‌ها debugging بشه.

javascriptcleancode
۳
۰
Hedieh
Hedieh
فرانت‌اند دولوپر | کد تمیز، طراحی دقیق
شاید از این پست‌ها خوشتان بیاید