مسیرها
/
JavaScript
JavaScript
/
تمرین‌ها
/
ربات بازیافت
ربات بازیافت

ربات بازیافت

تمرین یادگیری

مقدمه

دانستن این که نوع یک داده چیست، اغلب برای اجرای روان و بدون خطای کد بسیار مهم است.

JavaScript چندین روش برای بررسی نوع یک مقدار یا شیء دارد.

Note

سازوکارهای بررسی نوع در JavaScript می‌توانند تا حدی غیرقابل‌اعتماد باشند.

برای ایمنی نوع بیشتر و نوع‌های قوی‌تر، احتمالاً بهتر است از TypeScript استفاده کنید؛ زبانی که روی JavaScript بنا شده است، اما با نحو نوع‌دهی یک زبان با نوع ایستا.

عملگر typeof

عملگر typeof نوع عملوند خود را برمی‌گرداند. خروجی رشته‌ای است که با اسم یکی از انواع داده‌ی اولیه مطابقت دارد، به‌جز "null". همچنین می‌تواند "function" یا "object" باشد.

typeof undefined;
// => "undefined"

typeof true;
// => "boolean"

typeof 42;
// => "number"

typeof 'Hello, World!';
// => "string"

typeof function () {
  return 'Hello, World';
};
// => "function"

typeof [1, 2, 3, 4];
// => "object"

typeof { city: 'Stockholm', country: 'Sweden' };
// => "object"

به دلایل تاریخی.

عملگر instanceof

برای بررسی نوع یک شیء می‌توانید از عملگر instanceof استفاده کنید. این عملگر بسته به این که آیا عملوند دوم در زنجیره‌ی پروتوتایپ عملوند اول قرار دارد یا نه، به یک boolean ارزیابی می‌شود. برای روشن‌تر شدن مطلب، instanceof برمی‌گرداند که آیا عملوند اول نمونه‌ای از عملوند دوم یا یکی از کلاس‌های فرزند آن است یا نه. instanceof فقط روی شیءها کار می‌کند.

class Beverage {
  // ...
}

// The Coffee class is a child of the Beverage class.
class Coffee extends Beverage {
  // ...
}

const java = new Coffee();

java instanceof Coffee;
// => true

java instanceof Beverage;
// => true
Advanced

کلاس Array متدی به اسم Array.isArray() دارد که بررسی می‌کند آیا آرگومانش یک آرایه است یا نه.

در حالی که instanceof Array با آرایه‌ای که در قلمروی متفاوت ساخته شده باشد، مانند یک iframe در یک صفحه‌ی وب، کار نمی‌کند، Array.isArray() کار می‌کند.

دلیلش این است که کلاس Array در هر قلمرو سازنده‌ی متفاوتی دارد و هر iframe قلمرو خودش را دارد؛ یعنی تابع موجود در زنجیره‌ی پروتوتایپ متفاوت خواهد بود و همین باعث شکست خوردن instanceof Array می‌شود. Array.isArray() می‌تواند این را نادیده بگیرد و بهتر است هر جا ممکن بود همیشه استفاده شود.

همچنین می‌تواند از پس مثبت‌های کاذب هم بربیاید؛ جاهایی که یک شیء در واقع Array نیست و فقط Array را در زنجیره‌ی پروتوتایپ خود دارد.

({ __proto__: Array.prototype }) instanceof Array
// => true

Array.isArray({ __proto__: Array.prototype })
// => false

عملگر in

عملگر in برمی‌گرداند که آیا عملوند اول ویژگی‌ای از عملوند دوم است یا نه. بررسی نمی‌کند که آن ویژگی مقدار تعریف‌شده‌ای داشته باشد یا نه. ویژگی‌ای که مقدارش undefined تنظیم شده باشد، همچنان با in تشخیص داده می‌شود.

class Coffee {
  constructor() {
    this.temperature = 'hot';
    this.isDarkMatter = undefined;
  }

  coolDown() {
    this.temperature = 'warm';
  }
}

const espresso = new Coffee();

'temperature' in espresso;
// => true

'color' in espresso;
// => false

'isDarkMatter' in espresso;
// => true
Note

in برای ویژگی‌ها و متدهای ارث‌بری‌شده true برمی‌گرداند.

"coolDown" in espresso
// => true

"constructor" in espresso
// => true

برای جلوگیری از این، به‌جای آن از Object.hasOwn() استفاده کنید

تابع Object.hasOwn()

متد Object.hasOwn() برمی‌گرداند که آیا شیء مشخص‌شده ویژگی داده‌شده را خودش دارد (این ویژگی ارث‌بری نشده است و متد هم نیست).

class Coffee {
  constructor() {
    this.temperature = 'hot';
  }

  coolDown() {
    this.temperature = 'warm';
  }
}
const cappuccino = new Coffee();

Object.hasOwn(cappucino, 'temperature');
// => true

Object.hasOwn(cappucino, 'constructor');
// => false

Object.hasOwn(cappucino, 'coolDown');
// => false

دستورالعمل‌ها

دستورالعمل‌ها

شما توسط یک مرکز بازیافت استخدام شده‌اید. به‌دلیل کمبود فضا، همه‌ی محصولات روی یک نوار نقاله‌ی یکسان قرار می‌گیرند، اما این کار باعث شده مواد مختلف با هم مخلوط شوند و دیگر قابل استفاده نباشند. برای حل این مشکل، از شما خواسته شده است توابعی بنویسید که نوع یک محصول را تشخیص دهند.

1. بررسی کنید که آیا یک مقدار منطقی است

تابع isBoolean را پیاده‌سازی کنید که بررسی می‌کند آیا یک مقدار منطقی است یا نه.

isBoolean(true);
// => true

isBoolean(null);
// => false

2. بررسی کنید که آیا یک مقدار عدد است

تابع isNumber را پیاده‌سازی کنید که بررسی می‌کند آیا یک مقدار یک number یا bigint متناهی است، یعنی NaN یا Infinity نیست.

گاهی دستگاه خواندن شناسه‌ها دچار خطا می‌شود و یک مقدار غیرعددی را به‌صورت NaN (عدد نیست) یا Infinity می‌خواند. تابع شما باید بتواند این حالت را نیز به‌درستی مدیریت کند.

isNumber(42);
// => true

isNumber('Hello, World!');
// => false

isNumber(42n);
// => true

isNumber(NaN);
// => false

3. بررسی کنید که آیا یک مقدار شیء است

تابع isObject را پیاده‌سازی کنید که باید بررسی کند آیا مقدار یک شیء است. روی نوار نقاله، null به‌معنای هیچ است و شیء محسوب نمی‌شود.

isObject({ greeting: 'Hello' });
// => true

isObject(25n);
// => false

4. بررسی کنید که آیا یک رشته عددی است

تابع isNumericString را پیاده‌سازی کنید که باید بررسی کند آیا مقدار رشته‌ای است که فقط از رقم‌ها تشکیل شده یا از یک علامت منفی و پس از آن رقم‌هایی که نشان‌دهنده‌ی یک عدد منفی است. فقط اعداد صحیح در نظر گرفته می‌شوند؛ برای این بررسی ربات بازیافت، اعداد اعشاری عددی محسوب نمی‌شوند.

isNumericString(42);
// => false

isNumericString('42');
// => true

isNumericString('Hi!');
// => false

5. بررسی کنید که آیا یک شیء الکترونیکی است

تابع isElectronic را پیاده‌سازی کنید که بررسی می‌کند آیا یک شیء نمونه‌ای از کلاس ElectronicDevice ارائه‌شده یا یکی از کلاس‌های فرزند آن است.

class Duck {
  //...
}

class WashingMachine extends ElectronicDevice {
  //...
}

isElectronic(new Duck());
// => false

isElectronic(new WashingMachine());
// => true

6. بررسی کنید که آیا یک مقدار آرایه‌ی غیرخالی است

تابع isNonEmptyArray را پیاده‌سازی کنید که بررسی می‌کند آیا یک مقدار آرایه‌ی غیرخالی است.

isNonEmptyArray([1, 2, 3]);
// => true

isNonEmptyArray([]);
// => false

7. بررسی کنید که آیا یک مقدار آرایه‌ی خالی است

تابع isEmptyArray را پیاده‌سازی کنید که بررسی می‌کند آیا یک مقدار آرایه‌ی خالی است.

isEmptyArray([1, 2, 3]);
// => false

isEmptyArray([]);
// => true

8. بررسی کنید که آیا یک شیء ویژگی یا متد type دارد

تابع hasType را پیاده‌سازی کنید که بررسی می‌کند آیا یک شیء ویژگی یا متد type دارد.

class Keyboard(){
  type(){
    // ...
  }
}
hasType({ type:"car", color:"red" })
// => true

hasType({ color:"green" })
// => false

hasType(new Keyboard())
// => true

9. اگر یک شیء ویژگی یا متد id ندارد، خطا پرتاب کنید

تابع assertHasId را پیاده‌سازی کنید که در صورت نداشتن ویژگی id در یک شیء، یک Error پرتاب می‌کند.

اگر شیء ویژگی id را داشته باشد، نباید هیچ مقداری برگرداند.

assertHasId({ id: 42, color: 'red' });
// => undefined

assertHasId({ color: 'green' });
// Error: "Object is missing the 'id' property"

10. بررسی کنید که آیا یک شیء ویژگی id دارد

تابع hasIdProperty را پیاده‌سازی کنید که بررسی می‌کند آیا یک شیء ویژگی id دارد.

class SimpleData {
  constructor() {
    this.number = '42';
    this.id = 'BC269327FE1D9B95';
  }
}

class StealingData extends SimpleData {}

class MethodData {
  constructor() {
    this.number = '42';
    this._id = 'BC269327FE1D9B95';
  }

  get id() {
    return this._id;
  }
}

hasIdProperty(new SimpleData());
// => true

hasIdProperty(new MethodData());
// => false

hasIdProperty(new StealingData());
// => false

11. بررسی کنید که آیا یک شیء ویژگی type تعریف‌شده دارد

تابع hasDefinedType را پیاده‌سازی کنید که بررسی می‌کند آیا یک شیء ویژگی type دارد که undefined نیست.

hasDefinedType({ type: undefined, color: 'red' });
// => false

hasDefinedType({ type: 'car', color: 'green' });
// => true
ویرایش از طریق GitHub این لینک در پنجره یا زبانه‌ی جدیدی باز می‌شود
JavaScript Exercism

آماده‌اید ربات بازیافت را شروع کنید؟

در Exercism ثبت‌نام کنید تا JavaScript را همراه با 37 مفهوم159 تمرین و مربی‌گری انسانی واقعی یاد بگیرید و در آن استاد شوید، همه‌ی این‌ها رایگان.