首先明确ECMAscript中的数据类型分为两种:基本类型和引用类型
写在前面,本人北邮某专业研二在读,备战春招互联网大厂,通过查找资料对前面必问的数据类型方面做了一个总结,防止自己忘记时可以回顾,也希望能帮助到一部分人!
- 基本数据类型
即将一个基本类型的数据赋值给另外一个变量,是通过将原数据拷贝一份赋值的,两变量之间互不影响。
Undefined,Null,Boolean,Number,String,symbol(ES6),bigint
其中Number:
1:NaN(not a number),尽管字面不是一个数字的含义
typeof NaN === 'number'; // 尽管NaN是"Not-A-Number"的缩写,意思是"不是一个数字"
2:infinity
- 引用数据类型
即保存在内存中的对象,按引用访问
将一个引用类型的地址赋值给另一个变量,当该变量改变时,原变量也会随之改变。
1:object对象
普通对象/数组对象/正则对象/日期对象/JSON对象/Math数学函数对象/set/map...
2:function函数
普通函数/箭头函数/匿名函数/构造函数/自调用函数...
// Numbers
typeof 3 === 'number';
typeof 3.12224 === 'number';
typeof Math.LN2 === 'number';
typeof Infinity === 'number';
typeof NaN === 'number'; // NaN是"Not-A-Number"的缩写,意思是"不是一个数字",但是仍然属于number数据类型
// Strings
typeof "" === 'string';
typeof "bla" === 'string';
typeof (typeof 1) === 'string'; // typeof返回的肯定是一个字符串
// Booleans
typeof true === 'boolean';
typeof false === 'boolean';
// Symbols
typeof Symbol() === 'symbol';
typeof Symbol('foo') === 'symbol';
// Undefined
typeof undefined === 'undefined';
typeof blabla === 'undefined'; // 一个未定义的变量,或者一个定义了却未赋初值的变量
// Objects
typeof {a:1} === 'object';
// 使用Array.isArray或者Object.prototype.toString.call方法可以从基本的对象中区分出数组类型
typeof [1, 2, 4] === 'object';
typeof new Date() === 'object';
// 函数
typeof function(){} === 'function';
typeof Math.sin === 'function';
由上可以看出,其实使用关键子typeof关键字来进行类型检测是有一定的缺陷的!
数据类型检测:typeof
typeof value :返回当前值的数据类型,返回的数据类型是字符串
由以上结果可知typeof在数组,正则,日期,对象上的判断并不好,都是返回object
返回的结果都是字符串
局限性:
typeof null => “object” 类型
typeof 不能细分对象类型(检测普通对象或数组对象等都是返回"object")
原理:
所有的数据类型值在计算机中都是按照“二进制”进行存储
null的二进制值是“000000”
只要是对象都是以“000”开始的
typeof检测时是按照计算机存储的二进制值来检测的,所以检测null时也是返回“object”
关于typeof经典面试题(题主面试快手前端遇到的原题…
let a = typeof typeof typeof [12,23]
console.log(a) //"string"
/* 步骤分析
* typeof [12,23] => "object"
* typeof "object" => "string"
* typeof "string" => "string"
*/
//由于typeof返回的是字符串类型,对于第一次显然返回“object”,对一个字符串typeof显然是string,所以..
JS类型转换列表
数据类型的转化规则:
1:其他数据类型转化为布尔值
1: 使用 !可以转化为布尔值后取反
2: 使用!!可以转化为布尔类型
3:使用 Boolean() 进行转换
4:使用隐式转换
在循环或者判断条件中,条件处理的结果就是布尔类型
规则:
只有 0 null NaN undefined 空字符串,这五个值会变成布尔值得false,其余都是true
插曲:关于隐式转换
1:在js中,当运算符在运算时,如果两边数据不统一,CPU就无法计算,这时我们编译器会自动将运算符两边的数据做一个数据类型转换,转成一样的数据类型再计算。
2:这种无需程序员手动转换,而由编译器自动转换的方式就称为隐式转换
· 例如1 > "0"这行代码在js中并不会报错,编译器在运算符时会先把右边的"0"转成数字0`然后在比较大小
2:其他数据类型转化为Number类型
1:特定需要转化为number的:
-Number([value])
-parseInt([value])或parseFloat([value])
1:parseInt() 函数可解析一个字符串,并返回一个整数。如果不是字符串,先变成字符换在换砖。可以传第二个参数,表示进制数,默认是十进制。
2:parseInt(value,n) 就是把value看成是n进制的,然后在转化为十进制。如果字符串一0x开头,默认是十六进制。
n的范围2-36之间,不在这个之间的,除了0和10,剩下的结果都是NaN
3:内核:先把value变成字符串,然后从字符串左侧第一个字符开始查找,把找到的有效字符数字转化为数字,直到遇见一个非有效字符数字为止。
eg1:parseInt(12px12) :结果 12
eg2:parseInt(null) 先变成 parseInt("null") 发现找不到数字 :返回NaN
-parseFloat() 解析一个字符串,返回一个浮点数。
2:隐式转换:
-isNaN([value])
-数学运算:
特殊情况:+在出现字符串的时候,就变成了字符串拼接
-在 == 比较的时候,有些值需要转化为数字在进行比较,见下示例:
插曲:经典面试小示例
1:上面 console.log(![] == false) 因为==的优先级比较低,而且==左侧不是一个值而是一个表达式:
2:所以要先算出左侧表达式的值是多少,然后在比较类型是否相等,不相等的话左右均转化为数字Number类型,在进行比较,同上面!
3:其他数据类型转化为String类型
1:能使用的方法:
toString()/string()
2:隐式转换(一般都是调用 toString())
+加号运算时,如果某一边出现字符串,就是拼串的操作。
把对象转化为数字,需要先 toString() 转化为字符串,再去转化为数字number
基于alert/confirm/prompt/document.write..这些方式进行输出,都是把内容先转化为字符串..
4:在==比较的过程中数据转换的规则
类型一样的几个特殊点:
1:{} == {} :false 对象比较的是堆内存的地址
2:[] == [] :false
3:NaN == NaN :false NaN 跟任何值都不相等,包括它自己,与任何值相加都是NaN
类型不一样的几个转换规则:
1:null == undefined :true 但是换成 === 就是false,因为二者的类型不相等
2:剩下undefined/null 和其他任何数据类型都不相等。
3:字符串 == 对象 :要把对象转化成字符串在进行比较
4:剩下的如果 == 两边的数据不相等,都是需要转化成 number 然后咋进行比较的
插曲–经典类型转换小案例2:当a为何种方式时?能够满足下面条件成功打印OK?
1:== 比较时,当左右数据类型不一样时,会自动默认转换类型在进行比较。
2:对象转化为数字Number,需要先转化为字符串,然后在转换成数字,调用 toString() 方法来实现
3:但是直接调用默认使用的是 Object.prototype.toString() 方法来转化的,所以需要进行一个重写更改,满足我们的要求
4:于是在每次 == 比较时,都会调用,这样初值 i 会自增,就可以满足=1 2 3 这个条件!成功打印!
其他方法思路,不使用数据类型转化:使用vue2.0里面的defineProperty()…在vue3.0中对应的proxy
插曲–经典类型转换小案例3:打印最终的输出结果?
数组中的 map() 函数类似于 forEach() 函数:里面需要传递一个回调函数,依次循环数组中的每一项,每次都会执行一次回调函数
arr.map( (item,index) => {} )
只不过此处的回调函数是parseInt:
即: parseInt(10.18,0)
parseInt(0,1)
parseInt(10,2)
parseInt(25,3)
parseInt(23,4)
先转化成字符串,然后在考虑进制数进行转化
最终结果: 10 NaN 2 2 11 详细解析如下:
注意: parseInt('25',3) 中3进制,包含0 1 2 三个数,5 不符合,属于非有效字符,所以转化时不会考虑5,只考虑2即可!
完整解析:
//一些比较规则
//1. 对象和布尔值比较
//对象和布尔值进行比较时,对象先转换为字符串,然后再转换为数字,布尔值直接转换为数字
console.log([] == true); //false []转换为字符串'',然后转换为数字0,true转换为数字1,所以为false
//2. 对象和字符串比较
//对象和字符串进行比较时,对象转换为字符串,然后两者进行比较。
console.log([1,2,3] == '1,2,3'); // true [1,2,3]转化为'1,2,3',然后和'1,2,3', so结果为true;
//3. 对象和数字比较
//对象和数字进行比较时,对象先转换为字符串,然后转换为数字,再和数字进行比较。
console.log([1] == 1); // true `对象先转换为字符串再转换为数字,二者再比较 [1] => '1' => 1 所以结果为true
//4. 字符串和数字比较
//字符串和数字进行比较时,字符串转换成数字,二者再比较。
console.log('1' == 1) // true
//5. 字符串和布尔值比较
//字符串和布尔值进行比较时,二者全部转换成数值再比较。
console.log('1' == true); // true
//6. 布尔值和数字比较
//布尔值和数字进行比较时,布尔转换为数字,二者比较。
console.log(true == 1); // true
//许多刚接触js的童鞋看到这么多的转换规则就懵圈了,其实规律很简单,大家可以记下边这个图(是时候展现我高超的绘画技巧了)
//数据转换
//如图,任意两种类型比较时,如果不是同一个类型比较的话,则按如图方式进行相应类型转换,如对象和布尔比较的话,对象 => 字符串 => 数值 布尔值 => 数值。
console.log([] == false);
console.log(![] == false);
/这两个的结果都是true,第一个是,对象 => 字符串 => 数值0 false转换为数字0,这个是true应该没问题,
//第二个前边多了个!,则直接转换为布尔值再取反,转换为布尔值时,空字符串(''),NaN,0,null,undefined这几个外返回的都是true, 所以! []这个[] => true 取反为false,所以[] == false为true。
//还有一些需要记住的,像:
console.log(undefined == null) //true undefined和null 比较返回true,二者和其他值比较返回false
console.log(Number(null)) //0
总结:到这里,基本的数据类型知识和相关的内容介绍完毕,其中放了部分的面试题目,比较具有代表性,当时想要更加得心应手的完成大厂面试题目,还是需要理解扎实基础知识,而不是停留于表面!