トラック
/
JavaScript
JavaScript
/
演習
/
リサイクルロボット
リサイクルロボット

リサイクルロボット

学習演習

はじめに

データの型が何であるかを知ることは、コードをエラーなくスムーズに動かすうえで、しばしばとても重要になります。

JavaScriptには、値やオブジェクトの型を調べる方法がいくつかあります。

Note

JavaScriptの型チェックの仕組みは、やや信頼性に欠けることがあります。

型の安全性を高め、より強い型を使いたいなら、TypeScriptの利用をおすすめします。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"

[歴史的な理由][typeof null is "object"]からです。

instanceof演算子

オブジェクトの型を調べるには、instanceof演算子を使います。 これは、2番目のオペランドが1番目のオペランドのプロトタイプチェーンに含まれるかどうかに応じて、booleanを返します。 もう少し詳しく言うと、instanceofは、1番目のオペランドが2番目のオペランド、またはその子クラスのインスタンスかどうかを返します。 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()というメソッドがあります。

ウェブページのiframeなど、別のレルムで作られた配列に対してはinstanceof Arrayは機能しませんが、Array.isArray()なら機能します。

これは、Arrayクラスがレルムごとに異なるコンストラクターを持つためです。各iframeは独自のレルムを持つので、プロトタイプチェーン上の関数も異なるものになり、instanceof Arrayは失敗します。 Array.isArray()はこの違いを無視できるので、可能なときは常にこちらを使うべきです。

また、オブジェクトが実際にはArrayではなく、プロトタイプチェーンにArrayを持つだけという誤検知も防げます。

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

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

in演算子

in演算子は、1番目のオペランドが2番目のオペランドのプロパティかどうかを返します。 プロパティに値が定義されているかどうかは調べません。 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でもないかどうかを確認します。

IDを読み取る装置がときどき故障して、数値でない値を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関数を実装してください。この関数は、オブジェクトにundefinedではないtypeプロパティがあるかどうかを確認します。

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

hasDefinedType({ type: 'car', color: 'green' });
// => true
GitHubで編集する リンクは新しいウィンドウまたはタブで開きます
JavaScript Exercism

リサイクルロボットを始める準備はできましたか?

Exercismに登録すれば、37個のコンセプト159個の演習、そして本物の人間によるメンタリングとともに、JavaScriptを学んでマスターできます。すべて無料です。