【JS基础】介绍几个值得收藏的变量类型判断

typeof

一般情况下:

  1. 用来判断值类型;
// 值类型
console.log(typeof '') // 'string'
console.log(typeof undefined) // 'undefined'
console.log(typeof true) // 'boolean'
console.log(typeof 1) // 'number'
  1. 用来判断是否为函数;
// 函数类型
function demo() {}
console.log(typeof demo); // 'function'
console.log(typeof Object); // 你new一个object就是一个函数 'function',object应该是个构造函数
  1. 用来判断是否为引用类型;
// 引用类型
console.log(typeof null); // object null显示为'object',是因为作者设计typeof语法的历史遗留问题,并不是期望此处引用一个对象的说法;
console.log(typeof {}); // object
console.log(typeof []); // object

来看看这个表达式有哪些局限性。

局限性一:使用new形式创造的变量,会判断为’object ’

console.log(typeof new String(''));

解释:
new出来的基本类型使用构造函数创建的,不止有变量内容,还有附带的属性方法,实质是个对象,所以显示object;

局限性二:判断NaN是’number’

console.log(typeof 3); // 'number'
console.log(typeof NaN); // 'number'

一般我们写代码声明变量也不会用new去创造,所以typeof还是很适用的。


instanceof

判断xxx是否是该类型的实例,结果为布尔值(本质是看变量的__proto__ 属性是否指向某个构造函数的prototype 属性)。用法:

console.log(xxx instanceof 类型)

// 以下为true
console.log(new String('123') instanceof String)
console.log(new Number(1) instanceof Number)
console.log(function(){} instanceof Object) // 因为顶层原型就是Object
console.log({} instanceof Object)
console.log([] instanceof Array)
console.log([] instanceof Object) // 因为顶层原型就是Object

其实类似:

console.log(obj.__proto__.constructor === 类型)

var str = new String('123')
console.log(str.__proto__.constructor === String) // true

对于类来说也可以判断:

// 以下都为true
xiaoming instanceof Student
xiaoming instanceof People // 条件:Student继承至People 
xiaoming instanceof Object // 因为顶层原型就是Object

局限性一:不用new声明的基本类型,都显示false。

console.log('1' instanceof String) // false
console.log(1 instanceof Number) // false
console.log(true instanceof Boolean) // false

个人理解是因为instanceof语法并没有触发基本类型的包装对象;

局限性二:undefined、null、NaN这三个没有可实例化的构造函数,直接报错。

var obj = null
console.log(obj instanceof null) // 报错

var obj = undefined
console.log(obj instanceof undefined) // 报错

console.log(NaN instanceof NaN) // 这个也是报错的

不过还是可以用来判断是不是自己写的类

function Person(name, age) {
    this.name = name;
    this.age = age;
}
var person = new Person("小明", 12);
console.log(person instanceof Person) // true

constructor

哎,这个我也不喜欢用,不过可以用来判断数组(一般第三方库里用来做辅助判断)。判断xxx的构造函数是谁,用法:

console.log(xxx.constructor === Array)

// 判断为String
console.log(''.constructor) 
console.log(new String('').constructor)

// 判断为Array
console.log([].constructor) 
console.log(new Array().constructor) 

// 判断为Number
let num = 1
console.log(num.constructor) // 注意:直接  1.constructor  会报错
console.log(new Number(1).constructor)

// 判断为Object
console.log({}.constructor) 

// 判断为Boolean
console.log(true.constructor)

// 判断为Function
function demo() {}
console.log(demo.constructor) 

局限性一:undefined、null、NaN没有构造函数,直接报错。

局限性二:使用不安全,因为contructor的指向是可以改变的。


Object.prototype.toString.call()

这个几乎无敌,就是太长了。意思是使用call方法,改变最外层Object的this指向,指向()内的变量,让最外层Object的toString方法为()内变量使用。

console.log(Object.prototype.toString.call(null))      // '[object Null]'

console.log(Object.prototype.toString.call(undefined)) // '[object Undefined]'

console.log(Object.prototype.toString.call(''))        // '[object String]'

console.log(Object.prototype.toString.call(1))         // '[object Number]'

console.log(Object.prototype.toString.call(true))      // '[object Boolean]'

console.log(Object.prototype.toString.call([]) )       // '[object Array]'

console.log(Object.prototype.toString.call({}))        // '[object Object]'

console.log(Object.prototype.toString.call(fn))        //'[object Function]'

还可以判断Date类型正则表达式

var date = new Date();
console.log(Object.prototype.toString.call(date))      //'[object Date]'

var reg = /[^\d]/g;
console.log(Object.prototype.toString.call(reg))      //'[object RegExp]'

虽然这么牛逼,但是还是有局限性的

局限性一:NaN还是判断为Number 。

console.log(Object.prototype.toString.call(NaN))       // '[object Number]'

局限性二:对于自己写的类new出来的对象,只会判断为’[object Object]’ 。

function Person(name, age) {
    this.name = name;
    this.age = age;
}
var person = new Person("小明", 12);
console.log(Object.prototype.toString.call(person)); 
// '[object Object]' 不是 '[object Person]'

isNaN()

为了解决一些运算过程中产出NaN的值,比如Number()转换,Math方法的一些运算错误等,isNaN()判断变量是否为NaN,用法。

console.log(isNaN(123)) // false
console.log(isNaN(NaN)) // true

局限性:因为()内如果不是纯数字类型,那么底层会先执行Number(),进而导致判断错误。

console.log(isNaN('a')) // true  
// 实际上先执行了Number('a'),拿到结果再看看是否为NaN

// 例子:
console.log(isNaN({})) // true
console.log(isNaN(['a'])) // true
console.log(isNaN([])) // false
console.log(isNaN([123])) // false
console.log(isNaN(['123'])) // false

个人感觉靠谱一些的方法是

方法一:

function checkNaN(value) {
  return typeof value === 'number' && isNaN(value);
}

方法二:利用NaN自己不等于自己的特性,NaN === NaN 为false

function checkNaN(value) {
	return value !== value
}

后面ES6出了个Object.is ()方法解决了NaN === NaN 为false的问题,可以理解为更加严格的===

console.log(Object.is(NaN, NaN)); // true

方法三:ES6的Number.isNaN()

Number.isNaN([123]) // false

这个方法是底层先判断是不是一个number类型,然后再看看值是不是NaN,是就返回true。

拓展:

let arr = [NaN]
arr.indexOf(NaN) // -1 找不到子项
arr.includes(NaN) // true

是因为两个方法实现的底层机制不一样。


val = !val

这个好哇,可以用来判断某个变量是否为undefined或者null

let val = null 
console.log(val = !val) // 为true

// 以下是自己看的小例子,可以忽略哈
const symbolFormat = (data, val, styb) => {
  val = !val ? '%' : val;
  if (isNaN(data)) return;
  return parseFloat(data).toFixed(styb || 2) != 0 ? val : '';
}

Array.isArray()

用这个方法可以判断是不是数组:

Array.isArray(arr) // 返回布尔值

这个方法的缺点是当伪数组(例如函数的arguments参数,DOM集合)使用伪数组.__proto__ = Array.prototype后,伪数组的判断就为真了。


总结

如果不想记上面这么多,可以参考我的个人判断习惯:

  • 一般情况下都可以用typeof
  • 数组用Array.isArray()方便;
  • NaN最好用自己封的函数;
  • 同时判断nullundefinedval = !val

求求给个赞吧,会有不定时更新补充…

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值