隐式转及显示类型转换

204 阅读5分钟

JS为什么有数据类型转换?

因为JS是一门动态语言,变量没有类型限制?变量的值随时都可以赋予任何值。 这也意味着,JS引擎没有办法在编译的时候确定变量的数据类型,必须得到运行的时候才能根据值来确认数据的类型。但是各种运算符对数据类型是有要求的,如果运算符发现运算子的数据类型和预期的不符,就会自动类型转换。

数据类型的转换方式有2种

1、强制转换;2、隐式转换。

强制转换:

所谓的强制转换,是需要程序员手动调用:Number()、String()、Boolean()这个3个函数,将数据转换成对应的值。

数值类型转换和判断方法

1、原始值的转换规则

Number() 函数的转换规则:只有参数是纯数字和布尔值,才能转成数值,否则全部转成NAN。除了Number(null)的是特殊情况值为0。 代码如下:

function primitiveToNumber(arg) {
	if (arg === null || arg === false) {
		return 0
	}
	if (arg === true) {
		return 1
	}
	let temp = arg + '';
	// 由于0~9和小数点的ASCII码范围是46~57,46='.' 47='/'除外
	// 小数点的个数
	let pointCount = 0
	for (var i = 0; i < arg.length; i++) {
		let code = arg.charCodeAt(i)
		// 判断是不是数字和小数点,如果不是直接返回NaN
		if (45 < code && code < 57 && code !== 47) {
			// 小数点的个数如果为2的时候直接返回NaN
			if (code === 46 && ++pointCount && pointCount === 2) {
				return NaN
			}

		} else {
			return NaN
		}
	}
	return arg * 1 //这一步其实也是隐式调用了内置函数Number
}

isNaN() 方法是用来判断参数的值是不是一个数字,如果不是返回true,否则返回false, isNaN方法等价于下面的方法:

function myIsNaN(arg) {
	return Number(arg).toString() === 'NaN' ? true :false ;
}
console.log(myIsNaN(null))//false
//因为Number(null)的值为0,所以myIsNaN输出肯定是false

parseInt() 方法接受2个参数,第二参数是转换进制,默认是10进制。就以默认的10进制为基础,总结一下转的规则:从参数的首位取出数字直到取出的不是数字就返回结果,如果首位不是数子则返回NaN,否则返回数值。除

2、引用类型转换格则:

除了Number([813])的值为813,数组有一个元素,且元素一定是数值类型或者null,其他的都是NAN,Number()对引用类的处理过程如下:

1、调用对象的valueOf方法,如果返回的原始值,就直接调用Number函数返回该值。

2、如果对象的valueOf方法的返回值不是原始值,

2-1:判断对象的valueOf方法的值,如果是数组且长度为1且存的值为数值,就直接返回该数组下标为0的值。

2-2:如果toString返回的不是一个对像,则调用toString方法返回的结果进行Number函数转换

2-3:否则报类型错误:不能将对象转换成原始值,实现的代码如下:

function myNumber(arg) {
	// 判断参数的数据类型是不是原始值 或者参数为null
	if(typeof(arg)!=='object'||arg===null){
		return primitiveToNumber(arg)
	}
	let myValueOf = arg.valueOf();
	if (typeof(myValueOf) !== 'object') {
		return primitiveToNumber(myValueOf)
	} else {
		//判断valueOh数返回的是不是数组,而且长度为1,且元素的值为数字或者为null
		if (myValueOf instanceof Array &&
			myValueOf.length === 1 &&
			(typeof(myValueOf[0]) === 'number' || myValueOf[0] === null)) {
			return primitiveToNumber(myValueOf[0]);
		} else if (typeof(arg.toString()) !== 'object') {
			return primitiveToNumber(arg.toString())
		}
		throw 'Uncaught TypeError: Cannot convert object to primitive value';
	}
}
}

验证2-3的代码的代码如下:

var obj = {
	valueOf: function() {
		console.log("调用了valueOf");
		return {}
	},
	toString: function() {
		console.log("调用了toString");
		return {}
	}
}

//Number(obj);
//myNumber(obj);

String()函数的转换规则:

1、如果是原始值直接返回 参数+''

2、如果参数是对象则返回类型字符串,如果是数组就返回数组中元素的字符串,调用的过程是与Number()的调用过程的第一步和第二换掉了,也就是先调用toString(),在调用valueOf();代码如下:

function myString(arg) {
	if (typeof(arg) !== 'object'||arg===null) {
		return arg + ""
	}
	let str = arg.toString()
	if (typeof(str) === 'string') {
		return str
	} else {
		let toValue = arg.valueOf()
		if (typeof(toValue) === 'object') {
			throw 'Uncaught TypeError: Cannot convert object to primitive value';
		}
		return toValue
	}
}

验证代码如下:

console.log(String(null),myString(null));
console.log(String(undefined),myString(undefined));
console.log(String(NaN),myString(NaN));
console.log(String(1),myString(1));
console.log(String('a'),myString('a'));
console.log(String(true),myString(true));

var obj = {
	valueOf: function() {
		console.log("调用了valueOf");
		return {}
	},
	toString: function() {
		console.log("调用了toString");
		return {}
	}
}

//toString(obj);
//myString(obj);

注:typeOf的返回值有6种情况:number、string boolean、object、undefined、function,typeOf(null)是object,Number(null)是0

Boolean()函数的转换规则: 除了这6个值:''、0、 false、 NaN、 null、 undefined返回false。其他值返回true,代码如如下:

function myBoolean(arg) {
	switch (arg+'') {
		case '':
		case '0':
		case 'false':
		case 'null':
		case 'NaN':
		case 'undefined':
			return false
		default:
			return true
	}
}

隐式类型转换:隐式转换的过程是:JS引擎根据运算符期望运算子的数据类型自动调了,需要转换的对应类型方法:String()、Number()、Boolean(),这个过程对程序员不可见。

非严格相等

==操作符对于不同类型的值,进行的比较如下图所示:

微信图片_20220111182732.jpg developer.mozilla.org/zh-CN/docs/…

隐式转换的优先级:number,object,string,boolean

1、number:无论是谁遇到我,你们都要隐式转换;

2、boolean:我无论遇到谁,都有变成number;

3、object:我无论遇到谁,都有变成primitive;

总结

1、undefined==null//true,除了这个情况他们不等于任何值。

2、 NaN不等任何值包括自己都不等。

3、数值转换:

3-1:原始值除了纯数字小数 、null、true、false。其他的全部转NaN。

3-2:引用类型除了[纯数字 / 小数]或者**[]**。其他的全部转为NaN

4、字符串

4-1:原始值总是返回自己本身的值+""

4-2:引用值总是返回 [ object Object ]

5、布尔值:除了 0 、'' 、false、 null、 undefined、 NaN这个6个值返回false,其他的全部返回true

6、typeof函数 总是返回以下6个值:number 、string 、boolean 、object 、function、undefined