第四章 变量、作用域与内存

98 阅读3分钟

一、原始值与引用值

保存原始值的变量按值访问,保存引用值的变量按引用访问。

当变量是原始类型时,它保存的值就是实际值,保存在栈内存中,而引用值保存在堆内存中,变量的值只是一个指针

1、值的复制

原始值复制时,复制的是实际的值,引用值复制时,复制的是变量保存的指针

image-20211109152306632.png

2、参数按值传递

JS中所有的函数参数都是按值传递的。 普通的原始值好理解,那么怎么理解一个对象按值传递呢?要理解这个问题,必须要理解对于一个存储着对象的变量来说,什么是它的值,什么是它的引用。

我们知道对于一个对象,它保存的实际值是一个地址,然后根据这个地址去找对应的存在堆内存中的对象。而书上说它是按值传递的,又说它的传递就和对象的复制是一样的,而对象的复制就是按地址复制的,因此对象的值就是对象栈内存内保存的地址。而地址就是对象的引用的依据,因此对象明明是按值传递的,表现的却和按引用传递的非常类似。书上说按值传递相当于复制,那么按引用传递就不是复制了。

3、instanceof 操作符

之前我们学习了typeof操作符可以用来判断类型,但对于对象它不是那么准确。JS提供了instanceof操作符,专门用来测试变量是哪个类型的对象。比如Object、Array、Function、Date、RegExp。任何引用值instanceof Object都是true。

二、上下文与作用域

每个上下文都有一个对应的变量对象,比如全局上下文对应window对象。在这个上下文中定义的变量和函数都存在于这个对象上。执行上下文中的代码时,会创建该对象的作用域链,它决定了代码访问变量或函数的顺序。内部作用域中的代码可以访问外部作用域,反之则不行。

执行上下文可分为全局上下文、函数上下文、块上下文,代码访问变量的顺序是从块--》函数--》全局的,直至找到该变量为止。

image-20211109145518721.png

如图,全局上下文中定义了变量a和函数father,他们都成为了window对象的属性,而在father函数中又定义了变量b和函数son,函数son中又定义了变量c,那么在son函数上下文中,可以访问c、b、a,在father函数上下文中,可以访问b、a,而在全局上下文中,只能访问到a。

image-20211109150147472.png

三 、垃圾回收与内存泄漏

JavaScript垃圾回收程序的常用策略是标记清理。当一个变量进入上下文,程序会给它加一个存在标记,当它不在上下文中或者不被上下文引用的时候,也会被加上一个离开标记,借此周期性的进行内存清理。