Js中的数据类型 包装对象 垃圾回收 按值传递
1. Js中的数据类型
Js中的数据类型分为两类:原始类型(primitive type)和对象类型(object type)
1.1. 原始类型
JavaScript中的原始类型包括数字(Number)、字符串(String)、布尔值(Boolean)、undefined、null
1.1.1. 数字
当一个数字直接出现在Js程序中,我们称之为数字直接量
i. 整型直接量:十进制整数、十六进制值、Es标准不支持八进制直接量(Es6严格模式禁止八进制直接量)
ii. 浮点型直接量:实数写法(整数部分和小数点和小数部分)、指数计数法
Js数字具有足够的精度,并可以极其近似于0.1,但是不能精确表示类似0.1这样简单的数字,这会带来一些问题
var a=0.3-0.2;//0.1的近似值
var b=0.2-0.1;//0.1的另外一个近似值
a==b;//false
1.1.2. 字符串
Js通过字符串来表示文本,字符串直接量是由单引号或双引号括起来的字符序列,由单引号定界的字符串中可以包含双引号,由双引号定界的字符串中也可以包含单引号。
1.1.3. 布尔值
指代真或假、开或关、是或否,只有两个值,保留字:true和false,任意Js的值都可以转换为布尔值,下面这些值会转换为false
undefined
null
0
-0
NaN
"" //空字符串
所有其他值,包括对象(数组)都会转换成true
1.1.4. null
null是Js的关键字,表示一个特殊值,常用来描述空值
1.1.5. undefined
undefined表示值的空缺,是变量的一种取值,表示变量没有初始化,如果查询对象属性或者数组元素的值不存在返回undefined说明这个属性和值不存在,如果函数没有返回值则返回undefined.undefined是预定义的全局变量,并不是关键字。null和undefined都不包含任何属性和方法,所以使用 **. **和[]来存取这两个值的成员或方法都会发生一个类型错误
包装对象
看下面这段代码:
var s="hello";
var l=s.length;
console.log(l)//5
在调用length的时候, JS引擎会先对原始类型数据进行包装 new String("hello")
然后对其方法进行调用 new String("hello").length
字符串既然不是对象,为什么会有属性,只要引用了字符串s的属性,Js会将字符串值通过调用new String(s)的方式转换成对象,这个对象继承了字符串的方法,并被用来处理属性的引用,一旦属性引用结束,这个新创建的对象就会销毁。
var s="test";//创建一个字符串
s.len=4;//临时创建字符串对象,给属性赋值,随即销毁对象
console.log(s.len)//undfined 新创建一个临时对象,读取len属性
在读取字符串、数字或布尔值的属性时,创建的临时对象称做包装对象,可通过String(),Number(),或Boolean()显式创建包装对象
1.2. 对象类型
除了原始类型外的就是对象类型了,对象(object)是属性(property)的集合,特殊对象举例:全局对象(global object)、数组(array)、函数。
1.2.1. 垃圾回收
JavaScript解释器有自己的内存管理机制,可以自动对内存进行垃圾处理(garbage collection),当不再有任何引用指向一个对象,解释器就知道这个对象没用了,然后自动回收它所占用的资源。
2. 不可变的原始值和可变的对象引用
2.1. 原始类型和引用类型值的比较
Js中的原始值与对象(引用类型)有着根本区别:原始值是不可更改的,任何方法都无法更改
数据类型 | 数据特点 |
---|---|
原始值 | 原始值的比较是值的比较,只有值相等才相等 |
对象(引用类型) | 两个对象有相同的属性以及相同的属性值也不相等,只有引用的是同一个对象才相等 |
2.2. 按值传递
访问一个变量,有按值传递和按引用传递
2.1.1. 原始类型按值传递
i. EMCAJavaScrip里面所有函数的参数传递都是按值传递
var a=5;
fun add(a){
a+=3;
}
add(a);
console.log(a) //5
调用函数时,传给形参的a,是var声明的变量a复制出来的一个副本,
修改这个副本不影响原变量(这里声明的变量a是原始类型中的数字类型)
ii.变量间赋值
var a=5;
var b=a;
b+=1;
console.log(b) //6
console.log(a) //5
2.1.2. 引用类型按值传递
var student=new Object()
function add(obj){
obj.name="Lily";
}
add(student);
console.log(student.name) //Lily
继续:
var b=student;
b.age=10;
student.sex="女"
console.log(student.age,b.sex) //10 "女"
调用add函数,student的地址值复制出完全相同的一份副本作为传入形参,这个地址指向student对象,obj空间所存的地址和student就都指向了共同的存储空间,修改任意一个的属性值,副本也随之改变
再来看一段代码
var student= new Object()
function add(obj){
obj.name = "Lily"
obj = new Object()
obj.name = "Tom"
return obj;
}
var newStudent=add(student)
console.log(student.name) //Lily
console.log(newStudent.name) //Tom
总结
两个变量间赋值时,以及作为变量给函数传参时,只是将原变量中的值复制一个副本给对方变量或形参变量
i. 对于原始类型的值,修改新变量,不影响原变量
ii. 对于引用类型的值的值,因为传参和赋值时,复制的是地址值的一个副本,新变量和旧变量指向了同一个地址,修改新的变量中的属性,原变量也随之变动
参考:
大神的文章:https://blog.csdn.net/weixin_39728230/article/details/80607294
犀牛书