JavaScript 类型检查指南

        JavaScript有一个强大的特性就是动态类型。使用者在声明变量不用指定变量类型,但这样往往会给开发者带来问题或困惑,尤其是在较大的项目中。因此,类型检查是任何JavaScript开发者的一项关键技能。

1.值类型

类型描述示例
undefined变量未被赋值。let x;
null值为空,一个空的对象引用。const x = null;
boolean逻辑值,truefalseconst x = true;
number数值。const x = 50;
bigint任意精度的整数。const x = 9007199254740991n;
string字符序列。const x = 'Hello!';
symbol可以用作对象属性的键的唯一值。const x = Symbol();
object属性的集合。const x = { a: 1, b: 2 };
function一个可调用的对象。const x = () => {};

2.原始类型检查

        上表中除了object和function之外,其他类型都是原始类型。原始类型通常比对象和函数更容易进行类型检查。这是因为原始类型是不可变的,这意味着它们的值不能被改变。因此,我们只需将一个值的类型与我们想要检查的类型进行比较即可。使用typeof运算符就可以得出值的类型。

2.1 undefined

        检查undefined的值可以直接将值与undefined进行比较。这与使用typeof运算符得到的结果完全相同。

const isUndefined = val => val === undefined;

isUndefined(undefined); // true

2.2 null

        检查空值只能通过将值与null本身进行比较来完成。这是因为typeof null返回的是object。

const isNull = val => val === null;

isNull(null); // true

2.3 boolean

const isBoolean = val => typeof val === 'boolean';

isBoolean(true); // true
isBoolean(false); // true
isBoolean('true'); // false
isBoolean(null); // false

2.4 number

        这里需要注意的是,使用typeof来检查数字时。NaN也会返回true,因此需要特殊处理下。

const isNumber = val => typeof val === 'number' && !Number.isNaN(val);

isNumber(1); // true
isNumber('1'); // false
isNumber(NaN); // false

2.5 bigint

const isBigInt = val => typeof val === 'bigint';

isBigInt(1n); // true
isBigInt(1); // false

2.6 string

const isString = val => typeof val === 'string';

isString('Hello!'); // true
isString(1); // false

2.7 symbol

const isSymbol = val => typeof val === 'symbol';

isSymbol(Symbol('x')); // true
isSymbol('x'); // false

2.8 原始值

        检查一个值是否属于任何原始类型有点麻烦。不能简单地使用typeof,因为它不适用于null。 那么,我们可以根据值创建一个对象并将其与值本身进行比较。如果该值是原始值,则该对象将不等于该值。

const isPrimitive = val => Object(val) !== val;

isPrimitive(null); // true
isPrimitive(undefined); // true
isPrimitive(50); // true
isPrimitive('Hello!'); // true
isPrimitive(false); // true
isPrimitive(Symbol()); // true
isPrimitive([]); // false
isPrimitive({}); // false

3.非原始类型检查

        对象和函数的行为与原始类型略有不同。虽然typeof可以解决部分问题,但对于对象,我们需要使用其他方法检查。

3.1 对象

        typeof对于null的返回值是'object'。与判断是否原始值类似,我们可以使用Object构造函数为给定值创建一个对象包装器。如果该值是null或undefined,则返回值为一个空对象。否则,返回的对象将与输入对象相同。

const isObject = obj => obj === Object(obj);

isObject([1, 2, 3, 4]); // true
isObject([]); // true
isObject(['Hello!']); // true
isObject({ a: 1 }); // true
isObject({}); // true
isObject(true); // false
isObject(null); // false
isObject(undefined); // false

3.2 函数

        函数可以直接使用 typeof 来检查。

const isFunction = val => typeof val === 'function';

isFunction(x => x); // true
isFunction('x'); // false

3.3 普通对象

        当一个对象由Object构造函数创建时,它被认为是普通的。这与数组、函数或类的实例(如Map)等其他对象不同。 为了检查一个值是否是普通对象,我们需要确保该值是存在的(不是null或undefined),它是一个对象,并且它的构造函数等于Object.prototype.constructor。

const isPlainObject = val =>
  !!val && typeof val === 'object' && val.constructor === Object;

isPlainObject({ a: 1 }); // true
isPlainObject(new Map()); // false

3.4 异步函数

        使用async关键字声明的函数被视为异步函数。对异步函数的类型检查需要使用Object.prototype.toString()和Function.prototype.call()来检查结果是否为'[object AsyncFunction]'。

const isAsyncFunction = val =>
  Object.prototype.toString.call(val) === '[object AsyncFunction]';

isAsyncFunction(function() {}); // false
isAsyncFunction(async function() {}); // true

3.5 生成器函数

        生成器函数可以像异步函数一样进行类型检查。它的检查结果为是否为[object GeneratorFunction]。

const isGeneratorFunction = val =>
  Object.prototype.toString.call(val) === '[object GeneratorFunction]';

isGeneratorFunction(function() {}); // false
isGeneratorFunction(function*() {}); // true

3.6 获取值类型

        如果需要处理类和其他自定义类型,可以获取值的类型的字符串表示。这里可以通过使用Object.prototype.constructor和Function.prototype.name来实现。

const getType = v =>
  v === undefined ? 'undefined' : v === null ? 'null' : v.constructor.name;

getType(undefined); // 'undefined'
getType(null); // 'null'
getType(true); // 'Boolean'
getType(1); // 'Number'
getType(1n); // 'BigInt'
getType('Hello!'); // 'String'
getType(Symbol()); // 'Symbol'
getType([]); // 'Array'
getType({}); // 'Object'
getType(() => {}); // 'Function'
getType(new Set([1, 2, 3])); // 'Set'

3.6.1 检查值是否属于类型

        将上边获取值类型扩展下,我们还可以检查一个值是否为特定类型。与之前一样,对于undefined和null需要特殊处理下,因为它们没有构造函数。

const isOfType = (type, val) =>
  ([undefined, null].includes(val) && val === type) ||
  v.constructor.name === type;

isOfType(undefined, undefined); // true
isOfType(null, null); // true
isOfType('Boolean', true); // true
isOfType('Number', 1); // true
isOfType('BigInt', 1n); // true
isOfType('String', 'Hello!'); // true
isOfType('Symbol', Symbol()); // true
isOfType('Array', []); // true
isOfType('Object', {}); // true
isOfType('Function', () => {}); // true
isOfType('Set', new Set([1, 2, 3])); // true

最近的热门开源项目有哪些?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农界的小蜜蜂

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值