前言
📫 大家好,我是南木元元,热衷分享有趣实用的文章,希望大家多多支持,一起进步!
🍅 个人主页:南木元元
目录
JS数据类型
3种转换类型
ToBoolean
ToString
ToNumber
对象转原始类型
隐式类型转换
结语
JS数据类型
首先我们需要知道,js中数据类型分为两大类:基本数据类型和引用数据类型。
7种基本数据类型分别是:
引用数据类型即对象Object,包含普通对象-Object,数组对象-Array,正则对象-RegExp,日期对象-Date,数学函数-Math,函数对象-Function。
在JS中,类型转换只有三种情况:
数据类型转换的基本规则见下表:
ToBoolean指其他类型转换为布尔类型的操作。
js中的假值只有0、-0、NaN、""、false、null、undefined,其它值转为布尔型都为true。
console.log(Boolean(0)); // flase console.log(Boolean(-0)); // flase console.log(Boolean(NaN)); // flase console.log(Boolean("")); // flase console.log(Boolean(null)); // flase console.log(Boolean(undefined)); // flase console.log(Boolean(false)); // flase //其它所有值都转为true,包括所有对象 console.log(Boolean([])); //true console.log(Boolean({})); //true console.log(Boolean("0")); //true console.log(Boolean(1)); //true
ToString指其他类型的值转换为字符串类型的操作。
转为字符串的规则:
null:转为"null"
undefined:转为"undefined"
Boolean类型:true转为"true",false转为"false"
Number类型:直接转换,如5转为"5"(不过那些极小和极大的数字会使用指数形式,如1e21转为"1e+21")
Symbol类型:直接转换(只允许显式强制类型转换,使用隐式强制类型转换会报错)
数组:转为由逗号分隔的一系列数字组成的字符串 ,如[1,2]转为"1,2"
普通对象:会调用Object.prototype.toString(),返回"[object Object]",如果对象有自己的 toString() 方法,字符串化时就会调用该方法并使用其返回值。
console.log(String(null)); //'null' console.log(String(undefined)); //'undefined' console.log(String(true)); //'true' console.log(String(false)); //'false' console.log(String(5)); //'5' console.log(String(1e21)); //'1e+21' console.log(String(Symbol("5"))); //"Symbol(5)" console.log(String([1, 2])); '1,2' console.log(String({})); // '[object Object]'
ToNumber指其他类型转换为数字类型的操作。
转为数字的规则:
console.log(Number(null)); //0 console.log(Number(undefined)); //NaN console.log(Number(true)); //1 console.log(Number(false)); // 0 console.log(Number("10")); //10 console.log(Number("")); //0 console.log(Number("10a")); //NaN console.log(Number(Symbol("a"))); //TypeError: Cannot convert a Symbol value to a number console.log(Number([])); // 0 console.log(Number(["1"])); // 1 console.log(Number({})); // NaN
上面提到了如果是对象,则会先被转为基本类型,那么这个过程到底是怎么样的?
其实,对象转原始类型,会调用内置的ToPrimitive方法,逻辑如下:
注意:Date是个例外,要先调用toString,再调用valueOf来转换
来看下面的几个例子:
1.有Symbol.toPrimitive()方法,优先调用返回。
var obj = { value: 3, valueOf() { return 4; }, toString() { return '5' }, [Symbol.toPrimitive]() { return 6 } } console.log(obj + 1); // 输出7
2.toString 返回的不是基本类型值,valueOf 返回的基本类型值。
// toString 返回的不是基本类型值,valueOf 返回的基本类型值 var obj = { toString: function () { return {}; }, valueOf: function () { return null; }, }; console.log(String(obj)); // "null"
3.valueOf和toString都没有返回原始类型,会报错。
// 先判断valueOf⽅法,再判断toString⽅法,返回的都不是基本类型值,报错 var obj = { valueOf: function () { return {}; }, toString: function () { return {}; }, }; console.log(Number(obj)); // Uncaught TypeError: Cannot convert object to primitive value
在开发中,为什么建议大家使用===而不是==呢?
其实主要原因就是需要避免==所带来的隐式类型转换,下面就来看看js中有着很多坑的隐式转换。
JavaScript中的隐式类型转换主要发生在+、-、*、/以及==、>、<这些运算符之间。而这些运算符只能操作基本类型值,所以在进行这些运算前的第一步就是将两边的值用上面的ToPrimitive方法转换成基本类型,再进行操作。
不同操作符的隐式转换规则不同。
两边有至少一个string类型变量时,两边的变量都会被隐式转换为字符串;其他情况下两边的变量都会被转换为数字。
1 + "23"; // '123' 1 + false; // 1 1 + Symbol(); // Uncaught TypeError: Cannot convert a Symbol value to a number "1" + false; // '1false' false + true; // 1
一律转换成数值后计算。
1 * "23"; // 23 1 * false; // 0 1 / "aa"; // NaN
两边都是字符串,则比较字母表顺序;其他情况下,转换为数字再比较。
"ca" < "bd"; // false "a" < "b"; // true "12" < 13; // true false > -1; // true
==的隐式转换规则相对来说比较复杂,它的转换规则如下:
其实可以概括一下:两边的值都尽量转成Number。
console.log(3 == true); //false console.log("0" == false); //true console.log("0" == 0); //true console.log({ a: 1 } == true); //false console.log({ a: 1 } == "[object Object]"); //true
了解了上面的规则后,来看下面几道经典的题。
1.[]==[]的结果是什么?为什么?
答案为false。
原因:==两边都是对象的话,仅当它们引用同一个对象时返回true。数组是引用数据类型,在创建两个不同的数组时,引用的是两个不同的对象,所以不同。
2.[] == ![]结果是什么?为什么?
答案为true。
原因:先算右边(!的优先级要大于==),右边的结果是布尔值,那么根据上面==的隐式转换规则4,两边都转换成数字然后进行比较。左边[]转换为数字为0。右边![] 首先是转换为布尔值,由于[]作为一个引用类型转换为布尔值为true,因此![]为false,进而在转换成数字,变为0。0 == 0 , 所以结果为true。
3.如何让if(a == 1 && a == 2)条件成立?
其实就是利用==的隐式类型转换以及对象转原始类型的过程。
var a = { value: 0, valueOf: function() { this.value++; return this.value; } }; // 利用隐式类型转换,对象需要先转原始类型,再应用隐式类型转换规则 console.log(a == 1 && a == 2);//true
🔥如果此文对你有帮助的话,欢迎💗关注、👍点赞、⭐收藏、✍️评论,支持一下博主~
上一篇:前端——7.图像标签和路径