Javascript的数据类型显隐式转换(保姆级教程)

前言

在js中,当运算符在运算时,如果两边数据不统⼀,CPU就⽆法计算,这时我们编译器会⾃动将运算符两边的数据做⼀个数据类型转换,转成⼀样的数据类型再计算。这种⽆需程序员⼿动转换,⽽由编译器⾃动转换的⽅式就称为隐式转换。对于即将面试的小伙伴,小编在这里祝愿大家offer拿到手软.

一. js数据类型

基本数据类型(也就是原始值):

Undefined、Null、Boolean、Number、String、Symbol(es6)、BigInt(es10)

引用数据类型

Object Array Function  Date

我们说万物皆对象,所以他们都是Object

二.类型转换

数据类型间的转换可分为:

  • 原始值间的转换:转换为Boolean、Number、String
  • 原始值转换为对象:转换为Object
  • 对象转换为原始值:有两种转换方式

1.原始值转换

字符串的转换ToString

原始值需要借助内建类型,String()来将一个非字符串类型强制转换为string,String()转换的过程是由语言规范ToString抽象操作处理的.

参数类型结果
Undefined"undefined"
Null"null"
Boolean如果参数是 true,返回 "true"。参数为 false,返回 "false"
Number又是比较复杂,可以看例子
String返回与之相等的值

布尔值的转换ToBoolean

原始值需要借助内建类型(原生类型), Boolean() 来将一个非字符串类型强制转换为 boolean , Boolean() 转换的过程是由语言规范 ToBoolean 抽象操作处理的。

参数类型结果
falsefalse
undefinedfalse
nullfalse
+0false
-0false
NaNfalse
''false

除了这六种转为false, 其余的都是true.

数值的转换ToNumber

原始值需要借助内建类型(原生类型), Number() 来将一个非字符串类型强制转换为 number , Number() 转换的过程是由语言规范 ToNumber 抽象操作处理的。

参数类型结果
Undefined NaN
Null+0
Boolean如果参数是 true,返回 1。参数为 false,返回 +0
Number返回与之相等的值
String这段比较复杂,看例子

Number 来转换一个字符串,会将其转为一个整数或浮点数,会忽略所有前导的 0, 如果有一个字符不是数字,结果都会返回 NaN。

2.对象转原始值

js有俩个不同的方法来执行转换,一个是toString,一个是valueOf. (真实暴露出来的)

Object.prototype.toString方法可以返回[[class]]内部属性

而js下的很多类根据自己的特点,定了更多版本的toString.

  • 数组的toString返回一个字符串,逗号隔开.
  • 函数的toString方法返回源代码字符串.
  • 日期的toString方法返回一个可读的日期和时间字符串.
  • RegExp的toString返回一个表示正则表达式直接量的字符串.

valueOf表示对象的原始值,默认的valueOf返回对象本身,日期会返回毫秒数.

是利用 ToPrimitive 方法,输入一个值,返回一个基本类型的值。

ToPrimitive(input[, PreferredType])

他接收俩个参数,第一个参数是input,表示要处理的值

第二个参数是PreferredType,表示希望转成的类型,可以是Number,String

如果不传入第二个PreferredType,如果 input 是日期类型,相当于传入 String,其余都是传入 Number。

如果传入的 input 是 null, undefined, string, number, boolean 会直接返回该值。

如果是 ToPrimitive(obj, Number).

  • 如果obj为基本类型,直接返回
  • 否则,调用valueOf方法,如果返回一个原始值,则Javascript将其返回.
  • 否则,调用toString 方法,如果返回一个原始值,则 JavaScript 将其返回。
  • 否则,JavaScript 抛出一个类型错误异常。

如果是 ToPrimitive(obj, String),处理步骤如下:

  • 如果 obj为 基本类型,直接返回
  • 否则,调用 toString 方法,如果返回一个原始值,则进一步转换为字符串返回。
  • 否则,调用 valueOf 方法,如果返回一个原始值,结果同上。
  • 否则,JavaScript 抛出一个类型错误异常。

2.1 valueOf  和 toString的返回值解析

控制台输出 Object.prototype,就可以看到 valueOf() 和 toString() 。而所有对象继承自Object,因此所有对象都继承了这两个方法。对 Js 常见的内置对象:基本包装类型(Number、String、Boolean)、单体内置类型(global、Math)、Date、Array、Function、RegExp,分别使用 toString() 和 valueOf() 得到的返回结果,做进一步分析。

valueOf():

var num = new Number('123');
num.valueOf(); // 123

var str = new String('12323adc');
str.valueOf(); // 12323adc

var bool = new Boolean('abc')
bool.valueOf(); // true

// 2. Date 类型返回一个内部表示:1970年1月1日以来的毫秒数

var date = new Date();
date.valueOf(); // 1608784980823

// 3. 返回对象本身

var obj = new Object({});
obj.valueOf() === obj; // true

var arr = new Array();
arr.valueOf() === arr; // true

var reg = new RegExp(/a/);
reg.valueOf() == reg; // true

var func = function() {};
func.valueOf() == func; // true

// 单体内置类型
global.valueOf() == global; // true
Math.valueOf() == Math; // true

toString() : 作用是返回一个反应该对象的字符串:

// 1. 基本包装类型返回原始值

var num = new Number('123abc');
num.toString(); // 'NaN'

var str = new String('123abc');
str.toString(); // '123abc'

var bool = new Boolean('abc');
bool.toString(); // 'true'

// 2. 默认的 toString()

var obj = new Object({});
obj.toString();   // "[object Object]"
global.toString() // "[object Window]"
Math.toString();  // "[object Math]"

// 3. 类自己定义的 toString()

// Date类型转换为可读的日期和时间字符串
var date = new Date();
date.toString(); // "Wed Oct 11 2017 08:00:00 GMT+0800 (中国标准时间)"

// 将每个元素转换为字符串
var arr = new Array(1,2);
arr.toString(); // '1,2'

// 返回表示正则表达式的字符串
var reg = new RegExp(/a/);
reg.toString(); // "/a/"

// 返回这个函数定义的 Javascript 源代码字符串
var func1 = function () {}
func1.toString(); // "function () {}"

function func2() {}
func2.toString(); // "function func2() {}"

2.2类型装换表分析和归纳

3.显示转换

人为的调用函数去转换:

  • 转换为字符串: toString() 和 String
  • 转换为数值: Number() , parseInt() , parseFloat()
  • 转换为布尔值: Boolean()
  • 转换为对象: Object() 
String(false)  // "false" 布尔值转换为字符串

Number("123")  // 123 字符串转换为数值

Boolean([])     // true 对象类型转换为布尔值

Object(123)   // new Number(123)      

4.隐式转换

常见的隐式转换:

  • 逻辑语句的类型转换: 当使用if , while , for时, 隐式转换为布尔值
  • 逻辑表达式: 
  1. ! 逻辑非,隐式转换为布尔值,并取反, !!俩次逻辑非,隐式转换为布尔值;
  2. || 和 && 会将非布尔值会将非布尔值操作数,隐式转换为布尔值,在判断;
  • 算数表达式:
  1. 递增递减++ --,一元加减 +a、- a(结果的符号取反),二元 -,乘法,除法,求模,隐式转换为 Number;
  2. +运算符:
    不同类型间的转换规则
    如果其中一个操作符是对象,则进行对象到原始值的转换(这里是通过 toString 方法获取);
    进行了对象到原始值的转换后,如果其中一个操作数是字符串,则另一个操作数也会转换成字符串,再进行连接;
    否则两个操作数都转换为数字(或者NaN),然后进行加法操作。
  •  == 运算符: 具体看例子

5.隐式转换的具体例子

  • 通过字符串连接符转换
//  +  字符串连字符

console.log(typeof(1 + '123')); // string  '1123'
console.log(typeof(true + '123')); // string  'true123'
console.log(typeof(null + '123'));  // string 'null123'
console.log(typeof(NaN + '123'));  // string 'NaN123'
console.log(typeof(undefined + 'str')) // string 'undefinedstr'

// --------------------------------
console.log([] + '123')  // '123'
console.log([1,2,3] + '123') // '1,2,3123'
console.log({} + '123')     
// '[object Object]123'  这里 + 代表字符串连字符而不是算数运算符,因此隐式转换:
// 通过toString() , 返回[object Object]
// 最后由字符串连接符连接


console.log({a:1} + '123')  // '[object Object]123'
  • 通过算数运算符转换
// +
console.log(123 + true);  // 123 + 1
console.log(123 + false);  // 123 + 0
console.log(123 + NaN);    // NaN
console.log(123 + undefined); // 123 + NaN =>  NaN
console.log(123 + null);  // 123 + 0 
// ---------------------------------
console.log(123 + {});   // '123[object Object]'
console.log(123 + {a:'1'}); // '123[object Object]'
console.log(123 + [1]);   // '1231'
console.log(123 + [1,2,3]); //'1231,2,3'
console.log([] + 123);   // '123'

// 下面 + 是以字符串连接符来看的

注释: 
1. 如[] + 123 时 , 隐式转换会先走valueOf() ,  返回 这个数组本身
2. 接着会走toString() 将数组转换成 '' 
3. 最后 '' + 123  , 结果才为字符串 '123' 



// -  算数运算符 , 其他类型全部转换成数字型 , 忘了的可以去查看上面的表格

console.log(123 - true);  // 123 - 1
console.log(123 - false);  // 123 - 0
console.log(123 - NaN);    // NaN
console.log(123 - undefined); // 123 - NaN =>  NaN
console.log(123 - null);  // 123 - 0 
// ---------------------------------
console.log([] - 123);   // 0 - 123 => -123
console.log(123 - {});   // NaN
console.log(123 - {a:'1'}); // NaN
console.log(123 - [1]);   // 122
console.log(123 - [1,2,3]); // NaN
  • 通过关系运算符
console.log('' == 0);//true   
console.log([] == 0);//true
console.log(false == 0);//true
console.log({} == 0);//false
console.log(NaN == 0);//false   
console.log(undefined == 0);//false  
console.log(null == 0);//false

//特殊情况:无视规则
console.log(NaN == NaN);//false
console.log(null == undefined);//true
console.log(null === undefined);//false null--object  undefined----undefined

//----------------------------------------------------------------------------------
console.log('2' > 10);//false
console.log('2' > '10');//true

// 注解:
// '2' > 10 比较的时候 会把 '2' 转换成 2  , 2 > 10 不用想肯定为false
// '2' > '10' 单个字符串比较是以uniCode码比较的
// charCodeAt 可以将其转换为uniCode码

console.log('2'.charCodeAt());//50
console.log('10'.charCodeAt());//49



console.log('a' > 'b');//false

console.log('a'.charCodeAt());//97
console.log('b'.charCodeAt());//98
console.log('z'.charCodeAt());//122
// a - z  97 - 122

console.log('a'>'A')//

console.log('A'.charCodeAt());//65
console.log('Z'.charCodeAt());//90
//A-Z    65-90
//A<Z<a<z

// 长条字符串从左到右依次比较  
console.log('abc' > 'b');//false
// 多个字符串比较从左往右依次单个比较(这里注意不会比完有一个不一样就比出结果了)  
// 第二个字符 b > a  ,所以最后的结果就是 'abc' >'aad'
console.log('abc' > 'aad');//true

---------------------------------------------------------------------------------------------------------------------------------

至此,本篇也算是完结了,希望小伙伴们看的这篇文章有不一样的收获.文章可能有点长,希望小伙伴们可以坚持看完,小编相信坚持后的你肯定是最自信的~

喜欢小编的可以点赞哦,关注小编不迷路~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值