轨道
/
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"

出于[历史原因][typeof null is "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()的方法,用来检查它的实参是否为数组。

对于在不同领域中创建的数组,比如网页里的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运算符返回第一个操作数是否为第二个操作数的属性。 它不会检查该属性是否已经有一个确定的值。 被设为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(Not a Number)或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,全部免费。