黑马程序员技术交流社区

标题: JS内存机制和运算符 [打印本页]

作者: 小江哥    时间: 2019-5-18 11:41
标题: JS内存机制和运算符
本帖最后由 小江哥 于 2019-6-22 15:42 编辑

每一种语言都会存在内存机制,往往是需要调用内存的时候占用一部分内存空间,当不需要调用的时候自动清除这部分内存(垃圾回收),在JS里也是这样,只是在某些时候,JS解析器(解释分析并运行JS代码的东西)不知道什么时候可以回收该内存(闭包就是这样,在后续会讲)。而且JS里的基本数据类型和引用数据类型占用内存的方法也不一样哦,下面就一一分析:


1基本数据类型只用栈内存


<script>
    var a=10;
</script>
当JS解释器在运行到这个代码时,会做两件事,一是先声明一个变量a,然后再给这个变量a赋值为数字10
那么在内存里这个过程是怎么实现的呢?
首先,会在栈内存(可以想象成堆叠起来的方块)里开辟一块给这个变量,然后直接在当前栈内存里给这个变量赋值数字10,不管赋值的是数字还是字符串,只要属于基本数据类型,都会占用栈内存空间,当多个变量值相等时,改变一个变量值,其余的变量不会发生改变,因为只是变量的值发生了改变。

2
引用数据类型同时使用栈内存和堆内存
<script>
    var a=new Array()   //数组的构造器写法
</script>
当JS解释器在运行到这个代码时,会做两件事,一是先声明一个变量a,然后再给这个变量a赋值为一个空数组
那么在内存里这个过程是怎么实现的呢?
首先,会在栈内存(可以想象成堆叠起来的方块)里开辟一块给这个变量,然后在堆内存(可以想象成无序排列的圆圈)里给这个数组开辟一个空间,接着栈内存里的变量会被赋值成堆内存的内存地址(一个指针,指向堆内存空间的挂钩,且唯一),所以引用数据类型同时使用了栈内存和堆内存,当多个变量都赋值为同一个数组(或者是对象)时,改变一个变量的属性,其余的变量的属性会发生改变,因为都指向一个堆内存,所以相当于直接对数组进行了操作。
可能这样写大家还是一脸懵逼,没事,咋们举个例子:
<script>
    var a=10,b=a   /*如果多个变量声明只写一个var关键字,需要将声明写在同一行,以逗号隔开*/
</script>
如果a=20;
b==a?,答案是肯定不等于,因为b当前的栈内存里面赋值的是数字10,只是a的栈内存赋值被改变成了20,相互不会影响。
再举一个例子:
<script>
    var a=[1,2,3]   //数组的字面量写法
    var b=a /*相当于b的栈内存里面赋值了a一样的内存地址,都指向同一个数组*/
    a[3]=4; /*给数组增加一个值,值为4,数组会在后续讲*/
</script>
b==a?,答案是相等的,我们可以打印下此时的b,console.log(b)。会在浏览器控制台打印出[1,2,3,4],为什么会这样呢?因为a的操作运用了数组的方法,相当于堆内存里的数组自身发生了变化,而栈内存里a和b的地址并没有发生改变
再举一个不同的例子:
<script>
    var a=[1,2,3]   //数组的字面量写法
    var b=a //相当于b的栈内存里面赋值了a一样的内存地址,都指向同一个数组
    a=[]; //给a重新赋值了一个空数组,改变了a栈内存的内存地址
</script>
这个时候a==b?肯定是不等的,因为这个时候,内存空间被会重新划分,栈内存里,a赋值为空数组的内存地址,b还是之前数组的内存地址,此时堆内存里面会有两个堆,一个是之前的数组,另一个是空数组。
最后给大家上一张图,可能会更好理解,不同数据类型的内存机制大家一定要好好理解,对后面的学习很重要。



JS里面不同变量和数据之间经常会用到运算符

1
一个等号=
JS里面一个等号可不是数学里的等于,而是赋值的意思,就是将等号后面的赋值给等号前面的

2
两个等号==和其余的数学运算符
两个等号才是数学里面的相等,可以比较==前后的值是否相等,数学里面的加减乘除在JS里也适用

只是这里有两个坑:
  • 一是加号+如果遇到前后不是纯数字会进行拼接,比如:1+”22”,只会得到字符串”122”,如果是1+22,就会得到23。
  • 第二坑是除了加号以外,所有的数学运算符在遇到字符串和数字计算时都会将字符串隐式转换成数字后再运算,比如:33-“22”会得到数字11,乘除和取余数都是一样。这个坑灵活运用起来也可以将字符串快速转换成数字,如:”22”*1或者”22”-0都可以将字符串22变成数字22


3
逻辑运算符和比较运算符
逻辑与&&        只有当前后两个都为真,才会得到true
逻辑或 ||          前后只要有一个为真,都会得到true
逻辑非!         将值取反,如果值为true,取反得到false  !=是不等于,不是逻辑运算符
逻辑运算符和两个等号一般用于判断,因为得到的值都是布尔值true或者false

4
位移运算符(用的相当少)
>>,<<,~ 这三个属于位于运算符,前两个是将值先转换成二进制,然后位移小数点再转换回十进制,最后一个也需要转换进制,取反码。这里只做了解,用的非常少

5
逗号运算符和函数运算符
(逗号用的也很少,面试可能会遇到,坑)
JS里面单独的逗号也属于运算符,意思是从左往右计算,会返回最后一个值
比如:
<script>
    var a=(1,2,3)   //最终a会赋值成3
</script>
函数运算符主要是指函数调用会用一堆圆括号();
比如:alert();这里是调用的window对象的方法

好了,讲了这么多运算符,那么它们之间有没有先后顺序呢?Bingo,运算符是有优先级的,目前Alan所了解的运算符里优先级顺序是:
数学运算符>逻辑运算符>赋值运算符>函数运算符>逗号运算符

举个例子:
<script>
    alert(3+5>5)   //会弹出true
    //这里有一个坑哦
    alert(1,2,3)   //会弹出1而不是3,因为函数运算符优先级比逗号运算符高
    alert((1,2,3))  /*如果像让逗号运算符先运算,只需在外面加一个圆括号,圆括号会使优先级提高*/
</script>

作者: zzzz2017    时间: 2019-5-21 11:19
222223333333333
作者: ~123~    时间: 2019-5-24 08:53
6666666666666666666666666666666666666




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2