JavaScript类型转换和类型判断

103 阅读8分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第21天,点击查看活动详情

一、类型转换

Number() 转换为数字, String() 转换为字符串, Boolean() 转换为布尔值。

JavaScript类型转换

JavaScript变量可以转换为新变量或者其他数据类型:

  • 通过JavaScript函数
  • 通过JavaScript自身自动转换

1、将数字转换为字符串

全局方法String()可以将数字转换为字符串,该方法可用于任何类型的数字,字母,变量,表达式;

String(x)         // 将变量 x 转换为字符串并返回
String(123)       // 将数字 123 转换为字符串并返回
String(100 + 23)  // 将数字表达式转换为字符串并返回

Number方法toString()也是同样的效果。

x.toString()
(123).toString()
(100 + 23).toString()

在Number方法中,还有很多数字转换为字符串的方法:

方法描述
toExponential()把对象的值转换为指数计数法。
toFixed()把数字转换为字符串,结果的小数点后有指定位数的数字。
toPrecision()把数字格式化为指定的长度。

2、将布尔值转换为字符串

全局方法String()可以将布尔值转换为字符串。

String(false)        // 返回 "false"
String(true)         // 返回 "true"

Boolean方法toString()也有同样的效果。

false.toString()     // 返回 "false"
true.toString()      // 返回 "true"

3、将日期转换为字符串

Date()返回字符串。

Date()      // 返回 Thu Jul 17 2014 15:38:19 GMT+0200 (W. Europe Daylight Time)

全局方法String()可以将日期转换为字符串

String(new Date())      // 返回 Thu Jul 17 2014 15:38:19 GMT+0200 (W. Europe Daylight Time)

Data方法toString()也有同样的效果。

obj = new Date()
obj.toString()   // 返回 Thu Jul 17 2014 15:38:19 GMT+0200 (W. Europe Daylight Time)

Data方法中,还有更多关于日期转换为字符串的函数:

方法描述
getDate()从 Date 对象返回一个月中的某一天 (1 ~ 31)。
getDay()从 Date 对象返回一周中的某一天 (0 ~ 6)。
getFullYear()从 Date 对象以四位数字返回年份。
getHours()返回 Date 对象的小时 (0 ~ 23)。
getMilliseconds()返回 Date 对象的毫秒(0 ~ 999)。
getMinutes()返回 Date 对象的分钟 (0 ~ 59)。
getMonth()从 Date 对象返回月份 (0 ~ 11)。
getSeconds()返回 Date 对象的秒数 (0 ~ 59)。
getTime()返回 1970 年 1 月 1 日至今的毫秒数。

4、将字符串转换为数字

全局方法Number()可以将字符串转换为数字。

字符包含数字(如"3.14")转换为数字(如3.14)。

空字符串转换为0.

其他字符串会转换为NaN。

Number方法中,还有更多关于字符串转为数字的方法:

方法描述
parseFloat()解析一个字符串,并返回一个浮点数。
parseInt()解析一个字符串,并返回一个整数。

5、一元运算符+

Operator + 可用于将变量转换为数字:

var y = "5";      // y 是一个字符串
var x = + y;      // x 是一个数字

如果变量不能转换,它仍然会是一个数字,但值为NaN:

var y = "John";   // y 是一个字符串
var x = + y;      // x 是一个数字 (NaN)

6、将布尔值转换为数字

全局方法Number()可将布尔值转换为数字。

Number(false)     // 返回 0
Number(true)      // 返回 1

7、将日期转换为数字

全局方法Number()可将日期转换为数字。

d = new Date();
Number(d)          // 返回 1404568027739

日期方法getTime()也有同样的效果

d = new Date();
d.getTime()        // 返回 1404568027739

8、自动转换类型

当JavaScript尝试操作一个“错误”的数据类型,会自动转换为“正确”的数据类型。

5 + null    // 返回 5         null 转换为 0
"5" + null  // 返回"5null"   null 转换为 "null"
"5" + 1     // 返回 "51"      1 转换为 "1"  
"5" - 1     // 返回 4         "5" 转换为 5

9、自动转换为字符串

当你尝试输出一个对象或一个变量的时候,JavaScript会自动调用变量的toString()方法:

document.getElementById("demo").innerHTML = myVar;

myVar = {name:"Fjohn"}  // toString 转换为 "[object Object]"
myVar = [1,2,3,4]       // toString 转换为 "1,2,3,4"
myVar = new Date()      // toString 转换为 "Fri Jul 18 2014 09:08:55 GMT+0200"

数字和布尔值也经常相互转换:

myVar = 123             // toString 转换为 "123"
myVar = true            // toString 转换为 "true"
myVar = false           // toString 转换为 "false"

下面的表展示了使用不同的数值转换为数字(Number),字符串(String),布尔值(Boolean)

原始值转换为数字转换为字符串转换为布尔值
false0"false"false
true1"true"true
00"0"false
11"1"true
"0"0"0"true
"000"0"000"true
"1"1"1"true
NaNNaN"NaN"false
InfinityInfinity"Infinity"true
-Infinity-Infinity"-Infinity"true
""0""false
"20"20"20"true
"Runoob"NaN"Runoob"true
[ ]0""true
[20]20"20"true
[10,20]NaN"10,20"true
["Runoob"]NaN"Runoob"true
["Runoob","Google"]NaN"Runoob,Google"true
function(){}NaN"function(){}"true
{ }NaN"[object Object]"true
null0"null"false
undefinedNaN"undefined"false

二、类型判断

1、typeof

typeof是一个操作符,其右侧跟一个一元表达式,并返回这个表达式的数据类型。

返回的结果用该类型的字符串(全小写字母)行使表示,包括以下7种:string、number、boolean、symbol、undefined、object、function等。

typeof 'a'; // string 有效
typeof 1; // number 有效
typeof true; //boolean 有效
typeof Symbol(); // symbol 有效
typeof undefined; //undefined 有效
typeof new Function(); // function 有效
typeof null; //object 无效
typeof [1] ; //object 无效
typeof new RegExp(); //object 无效
typeof new Date(); //object 无效

总结:

  • 对于基本类型,除 null 以外,均可以返回正确的结果。
  • 对于引用类型,除 function 以外,一律返回 object 类型。
  • 对于 null ,返回 object 类型。
  • 对于 function 返回  function 类型。

其中,null 有属于自己的数据类型 Null ,引用类型中的数组、日期、正则 也都有属于自己的具体类型,而 typeof 对于这些类型的处理,只返回了处于其原型链最顶端的 Object 类型。

2、instanceof

instanceof检测的是原型,表达式为:A instanceof B,如果A是B的实例,则返回true,否则返回false。

[] instanceof Array; // true
new Date() instanceof Date;// true
 
function Person(){};
new Person() instanceof Person;//true
 
[] instanceof Object; // true
new Date() instanceof Object;// true
new Person instanceof Object;// true

虽然instanceof能够判断出[]是Array的实例,但它认为[]也是Object的实例,为什么呢?

从instanceof能够判断出[]._proto_指向Array.prototype,而Array。prototype._proto_又指向了Object.prototype,最终Object.prototype._proto_指向了null,标志着原型链的结束。因此,[]、Array、Object就在内部形成了一条原型链,如下图所示:

 从原型链可以看出,[] 的 proto  直接指向Array.prototype,间接指向 Object.prototype,所以按照 instanceof 的判断规则,[] 就是Object的实例。依次类推,类似的 new Date()、new Person() 也会形成一条对应的原型链 。

因此,instanceof 只能用来判断两个对象是否属于实例关系 , 而不能判断一个对象实例具体属于哪种类型  

针对数组的这个问题,ES5 提供了 Array.isArray() 方法 。该方法用以确认某个对象本身是否为 Array 类型,而不区分该对象在哪个环境中创建。

if (Array.isArray(value)){
   //对数组执行某些操作
}

  Array.isArray() 本质上检测的是对象的 [[Class]] 值。

  [[Class]] 是对象的一个内部属性,里面包含了对象的类型信息,其格式为 [object Xxx],Xxx 就是对应的具体类型 。对于数组而言,[[Class]] 的值就是 [object Array] 。

3、constructor

当一个函数F被定义是,JS引擎会为F添加prototype原型,然后再在prototype上添加一个constructor属性,并让其指向F的引用。

当执行var f = new F()时,F被当成了构造函数,f是F的实例对象,此时F原型上的constructor传递到了f上,因此f.constructor == F

可以看出,F利用原型对象上的constructor引用自身,当F作为构造函数来创建对象时,原型上的constructor就被遗传到了新创建的对象上,从原型链角度讲,构造函数F就是新对象的类型。这样做的意义是,让新对象在诞生以后,就具有可追溯的数据类型。

同样,JavaScript中的内置对象在内部构建时也是这样做的,如下图所示。

总结:

  1. null 和 undefined 是无效的对象,因此是不会有 constructor 存在的,这两种类型的数据需要通过其他方式来判断。

  2. 函数的 constructor 是不稳定的,这个主要体现在自定义对象上,当开发者重写 prototype 后,原有的 constructor 引用会丢失,constructor 会默认为 Object。

4、toString

toString()是Object的原型方法,调用该方法,默认返回当前对象的[[Class]]。这是一个内部属性,其格式为[Object XXX],其中XXX就是对象的类型。

对于 Object 对象,直接调用 toString()  就能返回 [object Object] 。而对于其他对象,则需要通过 call / apply 来调用才能返回正确的类型信息。

  语法:Object.prototype.toString.call(value);

Object.prototype.toString.call('') ;   // [object String]
Object.prototype.toString.call(1) ;    // [object Number]
Object.prototype.toString.call(true) ; // [object Boolean]
Object.prototype.toString.call(Symbol()); //[object Symbol]
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 global] window 是全局对象 global 的引用