知道一份数据的类型,对代码能否顺利运行、不出错往往非常重要。
JavaScript 有几种方法可以检查一个值或对象的类型。
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
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
对于继承来的属性和方法,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
你被一家回收中心录用了。 由于空间不足,所有产品都被放在同一条传送带上,但这导致不同的材料混在一起,变得无法使用。 为了解决这个问题,你的任务是编写一些函数,用来识别产品的类型。
实现isBoolean函数,检查一个值是否为布尔值。
isBoolean(true);
// => true
isBoolean(null);
// => false
实现isNumber函数,检查一个值是否为_有限_的number或bigint,即不是NaN或Infinity。
有时,读取 ID 的设备会出现故障,把非数值读成NaN(Not a Number)或Infinity。
你的函数也应该能正确处理这种情况。
isNumber(42);
// => true
isNumber('Hello, World!');
// => false
isNumber(42n);
// => true
isNumber(NaN);
// => false
实现isObject函数,检查一个值是否为对象。
在传送带上,null什么都不是,也不被视作对象。
isObject({ greeting: 'Hello' });
// => true
isObject(25n);
// => false
实现isNumericString函数,检查一个值是否为只由数字组成的字符串,或者由一个减号后跟数字组成、表示负数的字符串。
只有整数才会被考虑;在回收机器人的这项检查中,小数不算数值。
isNumericString(42);
// => false
isNumericString('42');
// => true
isNumericString('Hi!');
// => false
实现isElectronic函数,检查一个对象是否为所提供的ElectronicDevice类的实例,或者是它的某个子类的实例。
class Duck {
//...
}
class WashingMachine extends ElectronicDevice {
//...
}
isElectronic(new Duck());
// => false
isElectronic(new WashingMachine());
// => true
实现isNonEmptyArray函数,检查一个值是否为非空数组。
isNonEmptyArray([1, 2, 3]);
// => true
isNonEmptyArray([]);
// => false
实现isEmptyArray函数,检查一个值是否为空数组。
isEmptyArray([1, 2, 3]);
// => false
isEmptyArray([]);
// => true
type属性或方法实现hasType函数,检查一个对象是否具有type属性或方法。
class Keyboard(){
type(){
// ...
}
}
hasType({ type:"car", color:"red" })
// => true
hasType({ color:"green" })
// => false
hasType(new Keyboard())
// => true
id属性或方法,就抛出错误实现assertHasId函数,如果对象缺少id属性,就抛出一个Error。
如果对象确实有id属性,则不应返回任何内容。
assertHasId({ id: 42, color: 'red' });
// => undefined
assertHasId({ color: 'green' });
// Error: "Object is missing the 'id' property"
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
type属性实现hasDefinedType函数,检查一个对象是否具有不为undefined的type属性。
hasDefinedType({ type: undefined, color: 'red' });
// => false
hasDefinedType({ type: 'car', color: 'green' });
// => true