JavaScript中判断数据的类型

typeof

当我们想判断一个对象是基本数据类型还是引用数据类型,使用typeof可以准确的判断。

// Numbers
typeof 37 === 'number';
typeof 3.14 === 'number';
typeof(42) === 'number';
typeof Math.LN2 === 'number';
typeof Infinity === 'number';
typeof NaN === 'number'; // Despite being "Not-A-Number"
typeof Number('1') === 'number';      // Number tries to parse things into numbers
typeof Number('shoe') === 'number';   // including values that cannot be type coerced to a number

typeof 42n === 'bigint';

// Strings
typeof '' === 'string';
typeof 'bla' === 'string';
typeof `template literal` === 'string';
typeof '1' === 'string'; // note that a number within a string is still typeof string
typeof (typeof 1) === 'string'; // typeof always returns a string
typeof String(1) === 'string'; // String converts anything into a string, safer than toString

// Booleans
typeof true === 'boolean';
typeof false === 'boolean';
typeof Boolean(1) === 'boolean'; // Boolean() will convert values based on if they're truthy or falsy
typeof !!(1) === 'boolean'; // two calls of the ! (logical NOT) operator are equivalent to Boolean()

// Symbols
typeof Symbol() === 'symbol'
typeof Symbol('foo') === 'symbol'
typeof Symbol.iterator === 'symbol'

// Undefined
typeof undefined === 'undefined';
typeof declaredButUndefinedVariable === 'undefined';
typeof undeclaredVariable === 'undefined';

// Objects
typeof {a: 1} === 'object';

// use Array.isArray or Object.prototype.toString.call
// to differentiate regular objects from arrays
typeof [1, 2, 4] === 'object';

typeof new Date() === 'object';
typeof /regex/ === 'object'; // See Regular expressions section for historical results

// The following are confusing, dangerous, and wasteful. Avoid them.
typeof new Boolean(true) === 'object';
typeof new Number(1) === 'object';
typeof new String('abc') === 'object';

// Functions
typeof function() {} === 'function';
typeof class C {} === 'function';
typeof Math.sin === 'function';

但是要注意:

当我们typeof null === 'object'; 得到了object,这是一个我们不期望的结果。

如何判断一个数据是基本数据类型还是引用数据类型?

const plainValues = ['number', 'string', 'boolean', 'bigint', 'symbol', 'undefined', 'null']

function isPlainValue(value) {
  if (value === null) {
    return true
  }
  return plainValues.includes(typeof value)
}
const flag = isPlainValue()
console.log(flag)

如何判断该变量是否是一个函数

function c() {}
const d = () => {}
class Person {}
function* gen() {}
async function asf() {}
const fn = new Function()
console.log(typeof c)
console.log(typeof d)
console.log(typeof Person)
console.log(typeof gen)
console.log(typeof asf)
console.log(typeof fn)

以上打印全都是function。

instanceof

P1 instanceof Person

instanceof 关键字是检测 p1对象的原型链上是否有Person构造函数的原型。一般用于自定义对象的判断。比如判断实例化对象是否属于某个构造函数。

实现一个instanceof

function instance(left,right){
      left=left.__proto__
      right=right.prototype
      while(true){
           if(left==null)
                return false;
           if(left===right)
                return true;
           left=left.__proto__
      }
}

当我们使用 const obj = Object.create(null) 创建一个对象时。obj instanceof Object 为false, 所以我们一般使用instanceof来判断自定义实例化对象。

如何判断一个数据是否是数组

Array.isArray(value)

Object.prototype.toString

Object.prototype.toString方法返回一个对象的字符表现串形式。

EcmaScript中定义的类型使用Object.prototype.toString可以精准的判断。

Object.prototype.toString.call(123) // [object Number]
Object.prototype.toString.call('str') // [object String]
Object.prototype.toString.call(true) // [object Boolean]
Object.prototype.toString.call(123n) // [object BigInt]
Object.prototype.toString.call(Symbol()) // [object Symbol]
Object.prototype.toString.call(undefined) // [object Undefined]
Object.prototype.toString.call(null) // [object Null]
Object.prototype.toString.call({}) // [object Object]
Object.prototype.toString.call([]) // [object Array]
Object.prototype.toString.call(Math) // [object Math]
Object.prototype.toString.call(JSON) // [object JSON]
Object.prototype.toString.call(new Function()) // [object Function]
Object.prototype.toString.call(new Date()) // [object Date]
Object.prototype.toString.call(new RegExp()) // [object RegExp]
Object.prototype.toString.call(new Error()) // [object Error]

判断一个函数是什么类型的函数

如果我们想判断一个函数是async标记的函数, 还是用generator标记的函数呢?也可以使用Object.prototype.toString

Object.prototype.toString.call(async function () {}) // [object AsyncFunction]
Object.prototype.toString.call(function* () {}) // [object GeneratorFunction]
Object.prototype.toString.call(async function* () {}) // [object AsyncGeneratorFunction]
复制代码

怎么区分普通函数和箭头函数

const arrow_fn = () => {}
function fn() {}
console.log(arrow_fn.prototype) // undefined
console.log(fn.prototype) // {constructor: ƒ}

但是这种方式也是不可靠的。

因为object可以通过定义一个Symbol来改变Object.prototype.toString()的行为。toStringTag属性,导致意外的结果。

const myDate = new Date();
Object.prototype.toString.call(myDate);     // [object Date]

myDate[Symbol.toStringTag] = 'myDate';
Object.prototype.toString.call(myDate);     // [object myDate]

Date.prototype[Symbol.toStringTag] = 'prototype polluted';
Object.prototype.toString.call(new Date()); // [object prototype polluted]

所以为了保险起见,在判断一个对象时, 我们先判断下 obj[Symbol.toStringTag] 是否存在。然后在 Object.prototype.toString()进行判断。当然,如果这个对象是我们可控的,我们就不用判断啦。而且这个方法的精度更高。

© 版权声明
THE END
喜欢就支持一下吧
点赞0赞赏
分享
评论 抢沙发
jurieo的头像 - 君霖驿站

昵称

取消
昵称表情代码图片