由于之前对typeof 和 instanceof 的概念有点模糊,刚好今天再看《JavaScript高级程序设计》的时候,看到第四章,第一节,第四小节 确定类型 的时候,就想着趁机对这块的知识点进行梳理,也当作学习笔记,以备后用。
一、typeof
typeof操作符最适合用来判断一个变量是否为原始类型,更确切地说,它是判断一 个变量是否为sring、number、boolean或undefined的最好方式。如果值是object或null,那么 typeof返回object。 《JavaScript高级程序设计》 第4章,第1节,第4小节
语法:
typeof variable
typeof 对基本类型、引用类型、Date、Function、RegExp 以及 Null 类型的判断
下来我们看看实际情况,
// 基本类型
let s = "Nicholas";
let b = true;
let i = 22;
let u;
console.log(typeof s); // string
console.log(typeof b); // boolean
console.log(typeof i); // number
console.log(typeof u); // undefined
// 引用类型
let o = {};
let a = [];
console.log(typeof o); // object
console.log(typeof a); // object
// Date、RegExp、Function
let d = new Date()
let r = /a-z/;
let f = function () {};
console.log(typeof d); // object
console.log(typeof r); // object
console.log(typeof f); // function
// null
let n = null;
console.log(typeof n); // object
typeof 对包装类型的判断
再看一下示例:
let sss = new String('sss')
let nnn = new Number(123)
let bbb = new Boolean(true)
let fff = new Function ()
console.log(typeof sss) // object
console.log(typeof nnn) // object
console.log(typeof bbb) // object
console.log(typeof fff) // function
使用new操作符,除Function外的所有构造函数的类型都是object。
let obj = new Number(value); // 构造函数
在这个例子中,变量 number 中保存的是一个值为 25 的原始数值,而变量 obj 中保存的是一个 Number 的实例。 《JavaScript高级程序设计》 第5章,第三节
typeof兼容性
根据《JavaScript高级程序设计》描述:
注意 typeof 操作符在用于检测函数时也会返回"function"。当在 Safari(直到 Safari 5) 和 Chrome(直到 Chrome 7)中用于检测正则表达式时,由于实现细节的原因,typeof也会返回"function"。ECMA-262 规定,任何实现内部[[Call]]方法的对象都应该在typeof 检测时返回"function"。因为上述浏览器中的正则表达式实现了这个方法,所以 typeof 对正则表达式也返回"function"。在 IE 和 Firefox 中,typeof 对正则表达式返回"object"。 《JavaScript高级程序设计》 第4章,第1节,第4小节
在MDN也找到了以下示例
typeof /s/ === 'function'; // Chrome 1-12 Non-conform to ECMAScript 5.1
typeof /s/ === 'object'; // Firefox 5+ Conform to ECMAScript 5.1
总结
由上面的示例以及《JavaScript高级程序设计》我们可以看出typeof 的使用场景有局限性:
typeof更合适判断原始类型string、number、boolean以及undefined的数据类型typeof无法准确判断引用类型Date、Object和Array,以及nulltypeof对Function和Regexp类型存在兼容性问题 【未验证】
二、instanceof
如果变量是给定引用类型的实例,则
instanceof操作符返回true。
语法:
let result = variable instanceof constructor
instanceof检测原始值
let sss = 'sss'
let nnn = 123
let bbb = true
console.log(sss instanceof String) // false
console.log(nnn instanceof Number) // false
console.log(bbb instanceof Boolean) // false
结果:使用instanceof检测原始值,结果返回false
instanceof检测原始值的包装类型以及Function、RegExp
如下示例:
let sss = new String('sss')
let nnn = new Number(123)
let bbb = new Boolean(true)
let rrr = new RegExp(/a-z/)
var fff = new Function()
console.log(sss instanceof String) // true
console.log(nnn instanceof Number) // true
console.log(bbb instanceof Boolean) // true
console.log(rrr instanceof RegExp) // true
console.log(fff instanceof Function) // true
结果:使用instanceof运算符检测原始值的包装类型与实例结果都是返回true,这并不局限于基本数据类型、引用类型,也可以是自定义类型。
instanceof检测自定义类型
如下示例:
// 声明一个动物 Animal 的构造函数
function Animal (optioins) {
this.options = Object.assign({}, optioins)
}
// 添加原型方法 showName
Animal.prototype.showName = function () {
console.log(this.options.name)
}
// 实例化一个Animal 对象 dog
let dog = new Animal({name: '旺财'})
dog.showName() // 旺财
console.log(dog instanceof Animal) // true
console.log(dog instanceof Object) // true
上例声明了一个Animal类型,然后实例化了一个dog, 然后使用instanceof来检测,这个实例是否是Animal类型,结果返回ture。
在用检测dog 是否是Object,结果也返回true, 说明dog即属于Animal又属于Object。
instanceof检测 Object.create(null);
let obj = Object.create(null);
console.log(obj instanceof Object) // false
instanceof检测null和undefined
console.log(null instanceof Object) // false
console.log(undefined instanceof undefined) // Right-hand side of 'instanceof' is not an object
那么instanceof是怎么来判断类型的呢?引用MDN上面对instanceof的描述MDN
instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。
读起来可能有点绕,我结合上面的示例用我的理解描述一下:
instanceof会查找当前实例对象的原型连,直到当前对象的原型连上找到该构造函数的prototype属性,如果找到了,返回true,否则返回false。其实就是判断某一实例是否是某一类型。
总结
综上所述:
instanceof检测包装类型与他对应的实例返回trueinstanceof检测原始类型、null以及使用Object.create()创建的对象,返回falseinstanceof不能检测undefined, 否则报错
三、typeof 与 instanceof 的区别
从使用场景方面对比
- 使用场景:
typeof更合适判断基本类型,对引用类型、构造函数的实例对象以及null无法判断出准确类型
instanceof用于判断实例对象是否是某一构造函数的实例化对象,从而判处该对象所属的类型。 这种方式是通过原型链查找。 - 返回值:
typeof可以准确判断出基本数据类型以及undefined类型,并返回表示该数据类型的字符串
instanceof可以判断实例对象的原型链是不是指向该构造函数
对具体类型返回值的对比
-
typeof更合适判断原始类型string、number、boolean以及undefined的数据类型 -
typeof无法准确判断引用类型Date、Object和Array,以及null -
typeof对Function和Regexp类型存在兼容性问题 【未验证】 -
instanceof检测包装类型与他对应的实例返回true -
instanceof检测原始类型、null以及使用Object.create()创建的对象,返回false -
instanceof检测undefined报错
四、使用原型上的toString方法判断类型更准确
Object.prototype.toString.call(''); // [object String]
Object.prototype.toString.call(1); // [object Number]
Object.prototype.toString.call(true); // [object Boolean]
Object.prototype.toString.call(undefined); // [object Undefined]
Object.prototype.toString.call(null); // [object Null]
Object.prototype.toString.call(new Function()); // [object Function]
Object.prototype.toString.call(new Date()); // [object Date]
Object.prototype.toString.call([]); // [object Array]
Object.prototype.toString.call(new RegExp()); // [object RegExp]
Object.prototype.toString.call(new Error()); // [object Error]
Object.prototype.toString.call(document); // [object HTMLDocument]
Object.prototype.toString.call(window); //[object Window] window是全局对象Window的引用
// data 数据 type 类型
// return: String | Boolean
function getType(data, type) {
if (data !== null || data !== undefined) {
let currentType = Object.prototype.toString.call(data)
currentType = slice(8, currentType.length-1);
return type ? currentType === type : currentType
}
}
getType('') // String
getType('', 'String') // true
至此,关于typeof 和instanceof的学习暂时告一段落,做以上记录。
感谢大家观看,如有错误欢迎指正!