精简《JavaScript高级程序设计》四 、变量,作用域,内存问题

精简《JavaScript高级程序设计》四 、变量,作用域,内存问题

第四章概况

4.1基本类型和引用类型的值

4.2执行环境及作用域

4.3垃圾收集

4.1基本类型和引用类型

ES变量包含基本类型值引用类型值

基本类型指的是简单的数据段,包括Undefined、Null、Boolean、Number、String

引用类型值指的是那些可能由多个值构成的对象,包括Object,可以添加属性和方法

ES6 引入了一种新的原始数据类型Symbol,表示独一无二的值。它是 JavaScript 语言的第七种数据类型

复制变量值

对于基本类型而言,如果从一个变量向另一个变量复制,会在变量对象上创建一个新值,然后将该值复制到为新变量分配的位置

var a = 1
var b = a

在这里插入图片描述

对于引用类型而言,同样也会复制一份放到为新变量分配的空间中,不同的是这个值实际上是一个指针,指针指向存储在堆中的一个对象,复制结束后,两个变量实际上引用了同一个对象

var obj1 = new Object()
var obj2 = obj1
obj1.name = "fur"
console.log(obj2.name) //fur

在这里插入图片描述

传递参数

注意:访问变量有按值和按引用两种方式,而参数只能按值传递

传递基本类型时会把值复制给一个局部变量(命名参数),传递引用类型时会把这个值在内存在的地址复制给一个局部变量,因此这个局部变量的变化会反映函数外部

function add(num){
	num +=10
	return num
}
var count = 20
var result = add(count)
console.log(result)//30
console.log(count)//20

因此基本类型不会印象函数外部的count变量,但是引用类型会改变

function setNum(obj){
    obj.num =30
}
var count = new Object()
count.num = 20
setNum(count);
console.log(count.num)//30

很多人错误理解为引用类型的参数是引用传递,其实是按值传递的,再看修改后的代码

function setNum(obj) {
		obj.num = 30
		console.log(obj) //Object { num: 30 }
		obj = new Object()
		obj.num = 40
		console.log(obj) //Object { num: 40 }
	}
	var count = new Object()
	count.num = 20
	setNum(count);
	console.log(count) //Object { num: 30 }
	console.log(count.num) //30

如果count是引用类型传递,那么count就会自动被修改为指向40,所以证明是值传递,实际上,函数内部重写obj,这个变量引用就是一个局部对象,函数执行完立即销毁。

书里这个地方说得有点理所当然,所以又找了找别的解释:

关键在于obj = new Object()则会个地方会覆盖obj保存的指向count的地址值,使其指向新地址,那么此时的obj已经是一个局部变量,而且地址的改变使你无论对它进行什么操作都不会影响到原来的obj上面来。

在这里插入图片描述

检测类型

typeof:适用于检测基本类型

instanceof:适用于检测引用类型

var name = "fur"
var u
var n = null
var o = new Object()
console.log(typeof name)//string
console.log(typeof u)//undefined
console.log(typeof n)//object,这个需要注意
console.log(typeof o)//object

instanceof:适用于检测引用类型

var arr = new Array()
var o = new Object()
console.log(arr instanceof Array)//true
console.log(arr instanceof Object)//true  因为Object包括Array
console.log(o instanceof Array)//false
console.log(arr instanceof Object)//true

4.2执行环境及作用域

执行环境定义了变量或函数有权访问的其他数据,决定它们自身的行为,每个执行环境都有与之关联的变量对象,环境中定义的所有变量和函数都保存在这个对象里。

作用域链:保证对执行环境有权访问的所有变量和函数的有序访问,即可以访问自己以及自己父级以上的变量

通过代码说明

var name = "fur"
function changeName(){
	if(name === "fur"){
		name = "fur1"
	}else{
		name = "fur2"
	}
}
changeName();
console.log(name)//fur1

由此,changeNamed的作用域链包括自己的变量对象和全局环境的变量对象。

没有块级作用域,这个专指var,作用域只能限制在函数内,而无法像Java一样限制在块级内,但是ES6已经出现了let和count两种新的声明变量的方法,可以实现块级作用域,let可以修改,count不可修改

4.3垃圾收集

JavaScript具有自动垃圾收集机制

原理:找到不再使用的变量,释放其内存,垃圾收集器会按照固定的时间间隔周期性执行,方式主要有标记清理

标记清除:变量进入环境打上标记“进入环境”,离开环境打上标记“离开环境”

管理内存

接触引用:数据不在用,可以将其值设置为null,用于全局变量和对象,局部的离开执行环境会被自动解除引用。

注意:解除引用不等于回收该值所占内存,还是需要等待垃圾收集器

码字不易,有用的话点个赞鸭!

精简《JavaScript高级程序设计》五、引用类型(上)

回顾《JavaScript高级程序设计》目录篇

posted on 2020-01-21 18:54  furfur-jiang  阅读(136)  评论(0编辑  收藏  举报