wisetc / practice

Practice conclusion
5 stars 0 forks source link

对于 js 变量类型的判断 #21

Open wisetc opened 5 years ago

wisetc commented 5 years ago

这是一行判断语句引发的bug,

if (typeof _vacantReason === 'object') {
  console.log(_vacantReason.value);
  // ...
}

假设存在变量 _vacantReason,该变量的类型可变,当其为对象时,取出其属性 value 的值。因为 _vacantReason nullable,也可能是其他的类型,只有当其为 object 时,取属性 value 才有意义;当其类型为字符串时,也不会报错,但是返回的结果可能是 undefined,当其为 null 时,会报错。

我们看一下下面几条语句的执行结果,

t1. typeof null

> a = null
> typeof a

结果为'object',如下图,

image

t2. typeof undefined

> b = undefined
> typeof b

结果为'undefined',如下图, image

t3. null instanceof Object

> a = null
> a instanceof Object

结果为false,如下图, image

t4. undefined instanceof Object

> b = undefined
> b instanceof Object

结果为false,如下图, image

t5. {} instanceof Object

> c = {}
> c instanceof Object

结果为true,如下图, image

再看字符串取属性,

> ''.p
> ''.toString

结果,字符串的属性,为其原型对象的属性,如下图, image

最后再来看看Function toString

运行的结果如下图,

image

结论

js 中 undefined 比较特殊,typeof null 为'object',nullundefined 都不是 Object 的实例,所以不能访问任何属性。

访问一个可变类型对象o的属性的时候,需要先对其类型进行判断,可以使用 o instanceof Object,也可以使用 Object.prototype.toString.call(o) === '[object Object]',但是前者 o 可为数组或者其他对象,他们也是 Object 的实例。故原先的判断条件应该修正为,

if (Object.prototype.toString.call(_vacantReason) === '[object Object]') {
  console.log(_vacantReason.value);
  // ...
}

避免了 _vacantReason 初值为 null 时,抛出异常。

wisetc commented 4 years ago

类型判断,is module,源码参考 redux-saga.

export const undef = (v: any) => v === null || v === undefined;
export const notUndef = (v: any) => v !== null && v !== undefined;
export const func = (f: any) => typeof f === 'function';
export const array = Array.isArray;
export const object = (obj: any) =>
    obj && !array(obj) && typeof obj === 'object';