说到类型转换几乎是开发中随处可见,包括隐式的和显式的转换。那么首先你的知道数据类型有哪些:
原始类型:Undefined、Null、Boolean、Number、String、Object、Symbol(es6新增)****、BigInt(es2020新增)
引用类型:Object包括 Array、Function、Date、RegExp、Math、Error等
通常拿到一个变量是需要做数据类型判断的,那么问题来了,怎么去判断数据类型呢?
1. typeof
typeof 操作符 返回值是 一个表示其数据类型的小写形式的字符串。
有2种使用方式:typeof(表达式)和typeof 变量名,第一种是对表达式做运算,第二种是对变量做运算。
typeof 返回值 总的有6种:string,number,object,function,undifined,boolean
直接看运算结果:
console.log(typeof 2) // number
console.log(typeof '2') // string
console.log(typeof true) // boolean
console.log(typeof undifined) // undifined
console.log(typeof null) // object
console.log(typeof []) // object
console.log(typeof {}) // object
var date=new Date();
var reg = /a/g;
var err=new Error()
var arg;
(function getArg(){
arg=arguments;
})();
console.log(typeof date) // object
console.log(typeof reg) // object
console.log(typeof err) // object
console.log(typeof arg) // object
var fn=function(){}
console.log(typeof fn) // function
从上述代码可以看出,typeof的弊端:
对 null的类型判断 不准确;
对引用类型的数据类型判断不准确;
总结得出:typeof并不能完全精准的检测除数据类型。
2. **Object.prototype.**toString()
在MDN中是这样描述的:
每个对象都有一个
toString()方法,当该对象被表示为一个文本值时,或者一个对象以预期的字符串方式引用时自动调用。默认情况下,toString()方法被每个Object对象继承。如果此方法在自定义对象中未被覆盖,toString()返回 "[object type]",其中type是对象的类型。
ps: js 一切皆对象
ps: 上述描述也验证了 字符串明明是基础类型 为什么可以 .toString() 进行调用
话不多说,下面直接来验证下:
var toString = Object.prototype.toString;
console.log(Object.prototype.toString.call(2)) // "[object Number]"
console.log(toString.call(2)) // "[object Number]"console.log(toString.call('2')) // "[object String]"
console.log(toString.call(true)) // "[object Boolean]" console.log(toString.call(null)) // "[object Null]"
var jay;
console.log(toString.call(jay)) // "[object Undifined]"
console.log(toString.call([])) // "[object Array]"
console.log(toString.call({})) // "[object Object]"
var date=new Date();
var reg = /a/g;
var err=new Error()
var arg;
(function getArg(){
arg=arguments;
})();
var fn = function(){};
console.log(toString.call(date)) // "[object Date]"
console.log(toString.call(reg)) // "[object RegExp]"
console.log(toString.call(err)) // "[object Error]"
console.log(toString.call(arg)) // "[object Arguments]"
console.log(toString.call(fn)) // "[object Function]"
上述代码可以看出:Object.prototype.toString 可以精准的判断出数据类型
3. 那么两者结合可以更好的判断数据类型
function type (obj) {
return typeof obj !== "object" ? typeof obj : Object.prototype.toString.call(obj).slice(8, -1).toLowerCase();
}
4. instanceof
**语法:**object instanceof constructor
instanceof 运算符用来检测 constructor.prototype 是否存在于参数 object 的原型链上。
function Car(make, model, year) {
this.make = make;
this.model = model;
this.year = year;
}
const auto = new Car('Honda', 'Accord', 1998);
console.log(auto instanceof Car); // true
console.log(auto instanceof Object); // true
需要注意的是,如果表达式
obj instanceof Foo返回true,则并不意味着该表达式会永远返回true,因为Foo.prototype属性的值有可能会改变,改变之后的值很有可能不存在于obj的原型链上,这时原表达式的值就会成为false。另外一种情况下,原表达式的值也会改变,就是改变对象obj的原型链的情况,虽然在目前的ES规范中,我们只能读取对象的原型而不能改变它,但借助于非标准的__proto__伪属性,是可以实现的。比如执行obj.__proto__ = {}之后,obj instanceof Foo就会返回false了。
[] instanceof Array // true
[] instanceof Object // true
{} instanceof Object // true
(() => {}) instanceof Function // true
(() => {}) instanceof Object // true
上述例子中,
[]
相当于 new Array() 出的一个实例,所以 arr.__proto__ === Array.prototype,而 Array属于 Object 子类型,即Array.prototype.__proto__ === Object.prototype,因此 Object 构造函数在
[]
的原型链上。函数类型判断解释也是同理。
可见 instanceof也是没办法 精准的判断出数据类型。
注意:
Object.prototype.__proto__ === null,岂不是说 [] instanceof null 也应该为 true,这个语句其实会报错提示右侧参数应该为对象,这也印证 typeof null 的结果为 object 真的只是javascript中的一个bug 。
4. valueOf 方法返回指定对象的原始值
MDN是这样描述的:
JavaScript调用
valueOf方法将对象转换为原始值。你很少需要自己调用valueOf方法;当遇到要预期的原始值的对象时,JavaScript会自动调用它。
默认情况下,
valueOf方法由Object后面的每个对象继承。 每个内置的核心对象都会覆盖此方法以返回适当的值。如果对象没有原始值,则valueOf将返回对象本身。
JavaScript的许多内置对象都重写了该函数,以实现更适合自身的功能需要。因此,不同类型对象的valueOf()方法的返回值和返回值类型均可能不同。
不同类型对象的valueOf()方法的返回值
对象
返回值
Array
返回数组对象本身。
Boolean
布尔值。
Date
存储的时间是从 1970 年 1 月 1 日午夜开始计的毫秒数 UTC。
Function
函数本身。
Number
数字值。
Object
对象本身。这是默认情况。
String
字符串值。
Math 和 Error 对象没有 valueOf 方法。
进入主题,转换规则:(看下边这个链接,写的挺好)