js数据类型必须得知道的那些事
记得刚学习js的时候,在变量的赋值上经常会出现一些自认为是莫名奇妙的bug,自己找了半天也找不出问题~
当然js的数据类型转化也是让我头疼不已~ 明明上一秒还是小明,下一秒就变成了小红,经常是让人摸不着头脑.最为一个有自知之明的前端小菜鸟,还是有必要花时间来整理一下这些知识点的 ,把关于数据类型的知识点给整理了一下~做个小小的分享
以下是本文的提纲
数据类型
基本类型
引用类型
不同数据类型的赋值区别
不同数据类型作为参数传递的区别
数据类型隐式转化
基本运算
1.字符串与数组相比
2.==与 = ==
3.布尔类型与其他类型
4.null和undefined
5.引用类型运算
数据类型判断
typeof
Object.prototype.toString.call()
到底什么是数据类型?
就是计算机里面有各种数据值,不同的数据值的处理方式和储蓄方式都不同,我们为这些值分好了类别,统称为 数据类型
通俗点来说,就是计算机也需要对人说人话,对鬼说鬼话~
但是...现实中总是那么残酷,来看几段代码先
//数据类型间的赋值
var a =1 ;
var b =a ;
function num (c){
c = 999;
}
num(a);
console.log(a)//1
console.log(b)//1
console.log(c)//999
var obj = {
a:1
}
var obj2 = obj;
console.log(obj2); //1
obj2.a= 10;
console.log(obj)
------------------------------------------------------
console.log(1 + 'abc') /1abc
var obj = {
width: '100'
};
obj.width + 20 // "10020"
----------------------------------------------------
var a = [1,2];
var b = [3,4];
console.log(a+b); //1,23,4
----------------------------------------------------------
true + 0 // 1</pre>
-
那为什么会出现这样的情况呢,明明上一秒还是字符串,下一秒就变成了number
-
数值与字符串相加,结果变成了字符串的拼接
-
数组间的相加虽然不常见,但是结果也是让人匪夷所思
为了弄清楚这些问题.我不得不查阅了大量资料,以及做一些必要的测试来搞懂他,首先还是要对js中的数据类型要有个大致的了解~
js中的数据类型总共分为2个大类, 基本类型,对象类型,也可以叫做值类型和引用类型
先来看看基本类型,常见的基本类型总共有5种
js中提供了一种检测当前变量的数据类型的方法,也就是typeof关键字,我们先来试试看
注意:[ typeof对于基本类型,除了 null 都可以显示正确的类型 ]
Number
String
Boolean
Undefined
Null
var a = 'abc';
var b = 1;
var c =true;
var d = undefined;
var e = null;
var f = [];
var g = {};
function h () {
console.log(1)
}
console.log(typeof(a)) //string
console.log(typeof(b)) //number
console.log(typeof(c)) //boolean
console.log(typeof(d)) //undefined
console.log(typeof(e)) //object</pre>
为什么null打印出来是object呢 , 原因在于这是js的一个语言bug,null 本身是基本类型。
原理是这样的,不同的对象在底层都表示为二进制,在 JavaScript 中二进制前三位都为 0 的话会被判断为 object 类型,null 的二进制表示是全 0,自然前三位也是 0,所以执行 typeof 时会返回“object”。
引用类型:
-
数组
-
function
-
Obj
var f = [];
var g = {};
function h () {
console.log(1)
}
console.log(typeof(f)) //object
console.log(typeof(g)) //object
console.log(typeof(h)) //object</pre>
在这里其实可以发现,typeof只可以检测基本的数据类型,而引用类型的检测不出具体的数据类型的,关于检测数据类型,我们在后面再看~
基本类型和引用类型之间的区别
我们先来看第一个问题:把boj赋值一份给obj2,当改变了obj2中的属性值,obj的属性值也发生了改变,
不同数据类型间赋值区别
-
简单数据类型是存在内存中的栈中的,而引用类型的数据是存在内存中的堆中的,但是变量的声明都是在栈上
-
赋值只是把栈中的内存地址给另外一个变量,基本数据类型就等于把值复制给了另一个,引用类型就等于把我的内存地址赋值给另外一个变量,而他们都指向同一个堆中的数据
-
而引用类型数据存储在堆中,栈中的地址指向堆,obj1改变堆中的数据,obj又跟她指向同一个.
//数据类型间的赋值
var a =1 ;
var b =a ;
console.log(a)//1
console.log(b)//1
var obj = {
a:1
}
var obj1 = obj;
console.log(obj2); //1
obj1.a= 10;
console.log(obj)</pre>
image.png
一张图简单的来理解
不同数据类型间传参区别
var a =1 ;
function num (c){
c = 999;
}
num(a);
console.log(c)//999
var obj = {
a:10
}
function changen(obj1){
obj1.a=30;
}
changen(obj);
console.log(obj.a) //30</pre>
image.png
数据类型隐式转化
-
字符串和数字比较,字符串会被转换数字
-
布尔值和其他类型比较,会被转换成数字
运算符
基本数据类型
我们发现,js在对不同数据类型做运算的时候,会把不同类型的变量进行转变,比如 1 + '1' = ‘11’,简单数据类型的隐式转化常见的有以下几种
-
字符串加数字,数字就会转成字符串(上面已经写了)
-
数字减字符串,字符串转成数字 (1 - '1' //0)
console.log(1-'1') // 0
- 如果字符串不是纯数字就会转成NaN。字符串减数字也一样, 乘,除,大于,小于跟减的转换也是一样。
console.log(1-'1a') //NAN</pre>
==与===
== 允许在相等比较中进行强制类型转换,而== = 不允许,如果两个值的类型不同,我们就需要考虑有没有强制类型转换的必要,有就用= =,没有就用===,不用在乎性能。
//字符串和数字之间的相等比较,将字符串转换为数字再进行比较
var a =1;;
var b ='1';
a==b //true
a===b //false</pre>
其他类型与布尔类型相比
//先将布尔类型转为数字
true //1
false //0
var a = true;
var b = '999';
a == b //false</pre>
null和undefined比较
console.log(null == undefined) //trun
console.log(null === undefined) //false</pre>
引用类型
var a = [1,2];
var b = [3,4];
console.log(a+b); //1,23,4</pre>
要解决这个疑问,先要了解以下es5的规范
ES5 规范11.6.1 节,如果某个操作数是字符串或者能够通过以下步骤转换为字符串的话,+ 将进行拼接操作。如果其中一个操作数是对象(包括数组),则首先对其调用ToPrimitive 抽象操作(规范9.1 节),该抽象操作再调用[[DefaultValue]](规范8.12.8节),以数字作为上下文
如果加其中的一个操作数是字符串(或者通过此规范能得到字符串),则进行字符串拼接,否则执行数字加法
ToPrimitive会做以下3件事:
1.先计算obj.valueOf(),,如果结果为原始值,则返回此结果 (obj值的是引用的数据类型)
2.否则.计算obj.toString(),如果结果是原始值,则返回此结果
3.否则,抛出异常
var arr = [1,2];
console.log(arr.valueOf()); // [1,2]
console.log(arr.toString()); // 1,2</pre>
数据类型检测
typeof(检查基本数据类型)
typeof对于基本数据类型判断是没有问题的,但是遇到引用数据类型(如:Array,obj,function)是不起作用的,输出的都是object,那个这个时候检查引用数据类型就要用到下面这个方法了
var f = [];
var g = {};
function h () {
console.log(1)
}
console.log(typeof(f)) //object
console.log(typeof(g)) //object
console.log(typeof(h)) //object</pre>
Object.prototype.toString.call() (检查引用数据类型)
var f = [];
var g = {};
function h () {
console.log(1)
}
console.log(Object.prototype.toString.call(f)); //[object Array]
console.log(Object.prototype.toString.call(g)); //[object Object]
console.log(Object.prototype.toString.call(h)); //[object Function]</pre>