那些年遗忘的总感觉似是而非的js类型转换

309 阅读4分钟

说到类型转换几乎是开发中随处可见,包括隐式的和显式的转换。那么首先你的知道数据类型有哪些:

原始类型: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 方法。

进入主题,转换规则:(看下边这个链接,写的挺好)

juejin.cn/post/684490…