js中数据类型分为基本数据类型
和引用数据类型
,基本数据类型
有:String、Number、Null、Undefined、Boolean、Symbol(新增)、BigInt(新增);引用数据类型
有:Object,Object中又含有Array、Function。众所周知js是一门弱类型语言,定义变量是可以不指定变量类型,只有在变量使用时才知道类型;而当变量之间类型不同但是要进行运算或是比较时会发生隐式类型转换,这就很容易导致代码出错。下面我们就来了解一下js中的强制类型转换
和隐式类型转换
;
基本数据类型都可以使用typeof
来判断,引用类型中需要注意的是typeof
无null、Array和Object的返回值都为’object’;这是因为JavaScript 中的值是由一个表示类型的标签和实际数据值表示的。对象的类型标签是 0。由于 null
代表的是空指针(大多数平台下值为 0x00),因此,null 的类型标签是 0,typeof null
也因此返回 "object"
。这是一个创建这门语言就有的bug,一直未被修复。
typeof 2 // 'number'
typeof null // 'object'
typeof Symbol(2) // 'symbol'
typeof 3n // 'bigInt'
typeof [] // 'object'
typeof {} // 'object'
typeof function(){} // 'function'
总结:
instanceof 运算符用于检测构造函数的 prototype
属性是否出现在某个实例对象的原型链上。这里涉及到构造函数、原型和原型链的知识,举个例子理解一下:
// 常量arr是调用Array的构造函数返回的实例
const arr = [1,2,3,4];
// arr实例可以调用Array数组中的属性和方法,arr的原型链指向Array原型中
arr.__proto__ === Array.prototype // true
// 所以就可以使用instanceof判断是否是数组
arr instanceof Array; // true
// 注意:上面讲到typeof无法区分Array和Object,这是因为Array的原型链指向Object的原型上,而原型链的终点是null,所以就会出现下面情况
arr instanceof Object; // true
// arr完整的原型链
arr.__proto__.__proto__.__proto__ === null;
上面例子只是简述了一下instanceof的查找原理,原型和原型链没有深入讲解,下次单独整理讲述一下;
总结:
constructor 属性返回Object的构造函数(用于创建实例对象)。可以理解为这个变量的构造函数是谁。可以为除了 null
和 undefined
(因为这两者没有相应的构造函数)之外的任何类型都有 constructor
属性;
// 原始类型
console.log((1n).constructor === BigInt); // true
console.log(('str').constructor === String); // true
console.log(Symbol(3).constructor === Symbol); // true
// 引用类型
console.log(([]).constructor === Array); // true
console.log(({}).constructor === Object); // true
// 内置函数对象的构造函数为 Function
console.log(Array.constructor === Function); // true
console.log(String.constructor === Function); // true
总结:
每个对象都有一个 toString()
方法,当该对象被表示为一个文本值时,或者一个对象以预期的字符串方式引用时自动调用。默认情况下,toString()
方法被每个 Object
对象继承。如果此方法在自定义对象中未被覆盖,toString()
返回 “[object type]”,其中 type
是对象的类型。
Object.prototype.toString.call(null).slice(8,-1); // Null
Object.prototype.toString.call([]).slice(8,-1); // Array
Object.prototype.toString.call({}).slice(8,-1); // Object
总结:
这里强制类型转换主要介绍的是其他类型转换为基本数据类型
,而基本数据类型转换引用类型需要看对应基本数据类型原型上是否有对应方法。
其他类型强制转换为string类型有两种方式,String(val)
和val.toString()
。其中需要注意的是val.toString()
无法转换null
和undefined
。因为toString()方法是调用目标值原型对象上内置的toString方法,而 null和
undefined`没有对应原型对象,所以无法调用toString()方法。
null.toString(); // TypeError: Cannot read properties of null (reading 'toString')
undefined.toString();// TypeError: Cannot read properties of null (reading 'toString')
String(null); // 'null'
String(undefined); // 'undefined'
String(1); // '1'
String({}); // '[object Object]'
String([]); // ''
其他类型转换为number,调用方法 Number
即可。其中需要注意的是对象转换为字符串是NaN
; 如果字符串中包含有不是数字的值转换也会变成NaN
。
Number(null); // 0
Number(undefined); // NaN
Number(true); // 1
Number(false); // 0
Number([]); // 0
Number({}); // NaN
Number('12'); // 12
Number('12a'); // NaN
强制转换为Boolean很简单,只需要调用方法Boolean()
即可。只有六种情况转换的值才为false,其他都为true。转换为false:0、false、NaN、' '、null、undefined
null和undefined是JS中比较特殊的值,undefined
表示’无’的原始值;null表示尚未存在的对象,他们都没有自己的原型对象;所以不存在其他类型转换为这两种类型。
当引用类型进行类型转换时,会调用js内部一个方法toPrimitive(), 此方法接收两个参数,一个参数为需要转换的对象,另一个方法接收一个期望类型,string或number。
触发隐式类型转换的场景:
+
加法运算符: -、/和*
运算符:==
相等和!=
不等于比较true
。null
,另一个操作数是undefined
,则返回true
。Boolean
,则将布尔操作数转换为 1 或 0。
true
,则转换为1
。false
,则转换为0
。valueOf()
和toString()
方法将对象转换为原始值。String
:true
仅当两个操作数具有相同顺序的相同字符时才返回。Number
:true
仅当两个操作数具有相同的值时才返回。+0
并被-0
视为相同的值。如果任一操作数为NaN
,则返回false
。Boolean
:true
仅当操作数为两个true
或两个false
时才返回true
。!
转换!
会将后面的数据先转成布尔值,然后取反。
<、<=、>、>=
比较转换console.log(123 + +'123' == '123123');
console.log({} == []);
console.log({} == true);
console.log('777' < '8');
// 思考题
100 + true + 222 + null + undefined + "123" + [] + null + false = ???
+'123'
发生隐式转换为数字的123,最后是246 == '123123'
;所以为false'[object Object]' == ''
;所以为false'[object Object]' == 1
; 所以为false。'NaN123nullfalse'
总结:
;
结尾;