一、typeof
1. typeof的返回值
简单数据类型(基本数据类型):Undefined、Null、Boolean、Number、String、Symbol。
复杂数据类型(引用类型):Object(本质上是由一组无序的名值对组成的,包括对象,Function,Array)。
ES6 引入了一种新的原始数据类型 Symbol ,表示独一无二的值,最大的用法是用来定义对象的唯一属性名。
宿主对象:JS所运行的环境提供的对象比如:BOM中的Window、DOM中的document。
2. typeof为什么要区分object和function?
1、《JavaScript高级程序设计》:从技术角度讲,函数在ECMAScript中是对象,不是一种数据类型。然而,函数也确实有一些特殊的属性,因此通过typeof操作符来区分函数和其他对象是有必要的。
2、在实际的使用过程中,有必要区分object和Function,所以typeof实现了这一功能。
3. typeof的语法
typeof是一个操作符而不是函数,所以用不用括号都可以。
typeof (表达式):对表达式做运算
typeof 变量名:对变量做运算。
console.log(typeof 15); //'number'
console.log(typeof 'str'); //'string'
4. typeof的特殊返回值
//返回值:NaN(typeof返回值宗为字符串类型,但是NaN是个例外,他是数值类型)
console.log(typeof 1/0);
//返回值:'number'
console.log(typeof (1/0));
console.log(typeof NaN);
console.log(typeof Infinity);
//返回值:'string'
console.log(typeof typeof (1/0));
//返回值:'symbol'
console.log(typeof Symbol());
console.log(typeof Symbol('foo'));
//返回值:'undefined'
console.log(typeof undefined);
//返回值:'object'
console.log(typeof [1,2,3]);
console.log(typeof new String());
//返回值:'function'
console.log(typeof function(){});
console.log(typeof Math.sin);
console.log(typeof (class c{}));
5. typeof的迷惑行为和不足之处(当心踩坑)
1.typeof null会返回‘object’。因为特殊值null会被认为是一个空对象引用。
2.typeof 数组 会返回‘object’。
3.typeof 正则表达式
在Safari 5以及之前版本,Chrome 7以及之前版本会返回‘function’,其他浏览器会返回‘object’。
4.typeof 宿主对象
在IE6、7、8中,大多数的宿主对象返回‘object’而不是‘function’,如typeof alert返回‘object’。而在非IE浏览器或IE9以上(包含IE9)的浏览器中,返回‘function’。
5.typeof 对象,
对于一些创建的对象(数组、null、部分浏览器中的正则和宿主对象),他们都会返回’object’。
二、instanceof
1. 为什么有了 typeof 运算符我们还需要 instanceof ?
typeof是判断参数是什么的实例,返回值为说明运算数类型的字符串。如果参数为引用类型,那么typeof会始终返回 ’ object ',所以用typeof来判断参数类型有很大的局限性。
有时,我们需要判断某变量是否为某个对象的实例,那么我们会用到instanceof运算符。
2. instanceof 的定义和用法
instanceof是用来判断一个对象在其原型链中是否存在一个构造函数的prototype属性。
- a instanceof b:判断a是否为b的实例,也可用于继承关系中。
- 如果b是c的父对象,a是c的实例,那么 a instanceof b 与 a instanceof c 的结果都为true。
function Person(){} //创建一个构造函数
const p1 = new Person();
console.log(p1 instanceof Person); //true
3. instanceof 的判断原理
如果只看定义,大家可能像我一样不太理解原型链和prototype属性这些,
说白了,instanceof 就是可以用来判断一个变量是否是属于某个对象的实例,instanceof检测的是这个变量的原型属于谁。
- instanceof的判断规则是沿着 Func 的 prototype 属性向上找,如果能找到同一个引用,就返回true,否则返回false。
- 每个函数都有 prototype 属性(存储的是原型对象),每个原型对象都有 proto (隐式原型)指向它构造函数的原型对象(prototype)。对象没有 prototype 属性。
- func._ proto_ 指向 Func.prototype
- Func._ proto_ 指向 Object.prototype
- 最终指向Object,也是验证了万物皆对象的思想。因此,func instanceof Func 和 func instanceof Object 的返回结果都是 true,func instanceof Function 的返回结果是 false。
4. instanceof的局限性
(1)instanceof无法直接判断原始数据类型
var str1 = 'hello word';
var str2 = new String('hello world');
console.log(str1 instanceof String); //false
console.log(str2 instanceof String); //true
我们可以这样来解决:
class PrimitiveString{
static [Symbol.hasInstance](x){
return typeof x === 'string'
}
}
console.log('hello world' instanceof PrimitiveString); //true
Symbol.hasInstance 可以理解为一个自定义 instanceof 行为的方法,上面代码的功能等于typeof (‘hello world’ === ‘string’)。
(2)instanceof 对于特殊类型无法判断
console.log(new Date() instanceof Date); //true
console.log(new Date() instanceof Object); //true
console.log([] instanceof Array); //true
console.log([] instanceof Object); //true
instanceof只能用来判断两个对象是否属于实例关系,而不能判断一个是里究竟属于哪种类型。
三、如何判断特殊类型
1. 数组判断方法
既然 typeof 和 instanceof 都不能判断数组类型,那么我们就没办法判断数组了吗?
当然不是,我们还可以用Array.isArray来区分数组和普通对象:
//Array.isArray
console.log(Array.isArray([1, 2, 3])); // true
console.log(Array.isArray({obj: 123})); //false
2. null判断方法
最简单也是最直接的方法,就是直接与null比较:
console.log( value === null );
四、Object.prototype.toString
除了上面的方法,Object.prototype.toString 也是一个很方便可以判断数据类型的方法。
(内容有点多,我纠结了半天要不要单独写,最后还是决定在这里简单说一下~)
Object.prototype.toString的用法非常简单,我举几个例子大家就明白它的用法了。
1. 判断基本类型
console.log(Object.prototype.toString.call(1)); //'[object Number]'
console.log(Object.prototype.toString.call(true)); //'[object Boolean]'
console.log(Object.prototype.toString.call(null)); //'[object Null]'
console.log(Object.prototype.toString.call(undefined)); //'[object Undefined]'
console.log(Object.prototype.toString.call('a')); //'[object String]'
2. 判断引用类型
console.log( Object.prototype.toString.call({}) ); //”[object Object]”
console.log( Object.prototype.toString.call([]) ); //”[object Array]”
function fn(){}
console.log( Object.prototype.toString.call(fn) ); //”[object Function]”