typeof的返回值是一个字符串,用来说明变量的数据类型;instanceof的返回值是布尔值,用于判断一个变量是否属于某个对象的实例。
typeof:
const type = typeof '中国万岁'; // string
typeof 666; // number
typeof true; // boolean
typeof undefined; // undefined
typeof Symbol(); // symbol
typeof 1n; // bigint
typeof () => {}; // function
typeof []; // object
typeof {}; // object
typeof new String('xxx'); // object
typeof null; // object
let a=new Number("a") //Number是js的内置对象
console.log(typeof a); //object
console.log(a); //Number构造函数,但是属性对应的值是NaN
let b=new Number(2) //或者new Number("2")
console.log(typeof b); //object
console.log(b); //Number构造函数,但是属性对应的值是2
通过以上例子可以看出,typeof只能准确判断原始数据类型和函数(函数其实是对象,并不属于另一种数据类型,但也能够使用 typeof 进行区分),无法精确判断出引用数据类型(统统返回 object)。
有一点需要注意,调用typeof null返回的是object,这是因为特殊值null被认为是一个空对象的引用(也叫空对象指针)。
如果想准确判断引用数据类型,可以用instanceof运算符。
instanceof:
instanceof运算符返回一个布尔值,可以用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上,通俗说就是用于判断某个实例是否属于某构造函数。再通俗一点就是,只要右边变量的prototype在左边变量的原型链上就返回 true,否则返回 false
const result = [];
result instanceof Array // true
const result = {};
console.log(result instanceof Object); //true instanceof 可以准确判断引用数据类型
const result = null;
console.log(result instanceof Object); //flase instanceof不能正确判断原始数据类型
console.log(result instanceof Null); //Null is not defined
const Person = function() {};
const p = new Person();
p instanceof Person; // true
console.log(p instanceof Object); //true
const message = new String('xxx'); //这个String构造函数是原生js自己带的
message instanceof String; // true
console.log(message instanceof Object); //true
let str = 'xxx'
str instanceof String // false
区别:
1.typeof 会返回一个运算数的基本类型,instanceof 返回的是布尔值
2.instanceof 可以准确判断引用数据类型,但是不能正确判断原始数据类型
3.typeof 虽然可以判断原始数据类型(null 除外),但是无法判断引用数据类型(function 除外)
4.原始数据类型null要想准确判断只有用 Object.prototype.toString.call(null) //"[object Null]"
关于instanceof的实现原理:
function myInstanceof(left, right) {
// 这里先用typeof来判断基础数据类型,如果是,直接返回false
if(typeof left !== 'object' || left === null) return false;
// getProtypeOf是Object对象自带的API,能够拿到参数的原型对象
let proto = Object.getPrototypeOf(left); // 等同于let proto=left.__proto__;
while(true) {
if(proto === null) return false;
if(proto === right.prototype) return true;//找到相同原型对象,返回true
proto = Object.getPrototypeof(proto); // proto=proto.__proto__;
}
}
也就是顺着原型链去找,直到找到相同的原型对象,返回true,否则为false
typeof和instanceof都有一定的弊端,并不能满足所有场景的需求。如果需要通用检测数据类型,可以使用Object.prototype.toString.call()方法:
Object.prototype.toString({}) // 所有的数据类型不加call都是"[object Object]"
Object.prototype.toString.call({}) // "[object Object]"
Object.prototype.toString.call(1) // "[object Number]"
Object.prototype.toString.call('1') // "[object String]"
Object.prototype.toString.call(true) // "[object Boolean]"
Object.prototype.toString.call(function(){}) // "[object Function]"
Object.prototype.toString.call(null) //"[object Null]"
Object.prototype.toString.call(undefined) //"[object Undefined]"
Object.prototype.toString.call(/123/g) //"[object RegExp]"
Object.prototype.toString.call(new Date()) //"[object Date]"
const Person = function() {};
console.log(Object.prototype.toString.call(new Person())); //[object Object]
Object.prototype.toString.call([]) //"[object Array]"
Object.prototype.toString.call(document) //"[object HTMLDocument]"
Object.prototype.toString.call(window) //"[object Window]"
注意,该方法返回的是一个格式为"[object Object]"的字符串。
封装函数:
为了更方便的使用,我们可以将这个方法进行封装:
function getType(obj){
let type = typeof obj;
if (type !== "object") { // 先进行typeof判断,如果是基础数据类型和函数,直接返回
return type;
}
// 对于typeof返回结果是object的,再进行如下的判断,正则返回结果
return Object.prototype.toString.call(obj).replace(/^\[object (\S+)\]$/, '$1');
}
getType([]) // "Array" typeof []是object,因此toString返回
getType('123') // "string" typeof 直接返回
getType(window) // "Window" toString返回
getType(null) // "Null"首字母大写,typeof null是object,需toString来判断
getType(undefined) // "undefined" typeof 直接返回
getType() // "undefined" typeof 直接返回
getType(function(){}) // "function" typeof能判断,因此首字母小写
getType(/123/g) //"RegExp" toString返回
js的字符串在进行大于(小于)比较时,会根据第一个不同的字符的ASCII码值进行比较。如果第一个字符的ASCII码值相同,则比较第二个;依次类推
console.log('2'>'11') //true //2的ASCII码值大 //所以同是字符型数字比较不会把字符整数转化成number型
console.log(2>'11') //false //一个字符型和一个number型运算时,除了加运算,其他的乘除取模减以及比较都会把字符整数转化成number型再去运算
console.log('11'/2) //5.5 typeof number
onsole.log(2+'11') //211 typeof string
console.log('2'+11) //211
console.log('15'>'3') //flase //3的ASCII码值大
console.log('15'>3) //true //一个字符型和一个number型运算时,除了加运算,其他的乘除取模减以及比较都会把字符整数转化成number型再去运算
console.log('a'>'b') //false
console.log('abc'>'a') //true
console.log('abc'>'acb') //false
JS的类型检测方法:
1.typeof ,但只能准确判断基本数据类型(null除外),无法精确判断出引用数据类型(function 除外)
2. instanceof通过判断原型,但只可以准确判断引用数据类型,但是不能正确判断原始数据类型,返回 true或 false
3.Object.prototype.toString.call()方法可以作为通用检测数据类型
JS中的NaN:
JavaScript中,NaN是一个特殊的数字值(typeof NaN的结果为number),是not a number的缩写,表示不是一个合法的数字。
1.NaN的产生:
Number('abc') // NaN
Number(undefined) // NaN
2.注意点:NaN是唯一一个和自身不相等的值:
//NaN 永远不会等于NaN,因为NaN虽然表示的不是数字, 但是具体值也是不同的,因此 NaN 不等于 NaN。
NaN === NaN // false
NaN == NaN // false
3.如何辨别NaN:
我们可以使用全局函数isNaN()来判断一个数值是不是一个非数字(并不是用来判断是不是NaN这个值):
isNaN(NaN) // true
isNaN(10) // false
4.NaN详解点此
5.附
let v=2
let r=8
console.log(v=r); //8 相当于执行完赋值返回v的值
console.log(v); //8