读书笔记--javaScript高级程序设计--第4章 变量、作用域和内存问题

175 阅读4分钟

JavaScript的变量是松散类型的,可以随时转换变量类型.

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

  1. 基本类型

    5个基本数据类型: undefined/Null/Boolean/Number/String 它们是按值访问的,可以操作保存在变量中的实际的值. (直接存放在栈内存之中)

  2. 引用类型

    引用类型的值是保存在内存中的对象, 不允许直接操作对象的内存空间,实际操作是在操作对象的引用(是存放在堆内存之中,操控的是栈内存中的"指针")

4.1.1 动态的属性

定义基本类型值和引用类型值的方式是类似的:创建一个变量并为该变量赋值。但是操作有很大区别,引用类型的值,可以添加属性和方法,也可以改变或者删除属性或方法。不能给基本类型的值添加属性,虽然不会报错,但是是没有意义的。

** #当复制保存在对象的某个变量时,操作的是对象的引用。但是添加属性时,操作的是实际的对象**

4.1.2 复制变量值

  1. 复制基本类型(值就保存在栈内存)的值,是创建一个新值。改变一个,另一个不受影响。
  2. 复制引用类型(值存在堆内存中,由栈内存通过指针建立联系)的值,是复制一个指针。改变一个,另一个也会跟着改变。

4.1.3 传递参数 (有点没明白哎,回头补一篇)

ECMAScript中所有函数的参数都是按值传递的。把函数外部的值复制给函数内部的参数,就是把值从一个变量复制到另一个变量。基本类型值的传递如同基本类型变量的复制一样,而引用类型值的传递,则如同引用类型变量的复制一样。

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

可以把ECMAScript函数的参数想象成局部变量

4.1.4 instanceof()

typeof()可以确定一个变量是字符串、数值、布尔值、还是undefined,
如果变量的值是一个对象或者null,则会返回“object”

语法: result = variable instanceof constructor

alert(person instanceof Object);   //变量person是Object吗?
alert(person instanceof Array);   //变量person是Array吗?
alert(person instanceof RegExp);   //变量person是RegExp吗?

根据规定,所有引用类型的值都是Object的实例,因此,在检测一个引用类型值和Object构造函数时, instanceof操作符始终会返回true。

4.2 执行环境及作用域

每个执行环境都有一个与之关联的变量对象(variable object)

全局执行环境是最外围的一个执行环境,根据ECMAScript实现所在的寄主环境不同而不同,表示执行环境的对象也不一样。在Web浏览器中,全局执行环境被认为是window对象。

每个函数都有自己的执行环境。

当代码在一个环境中执行时,会创建变量对象的作用域链(scope chain)

函数的作用域链包含多个对象:它自己的变量对象(其中定义着arguments对象)和全局环境的变量对象。

内部环境可以通过作用域链访问所有的外部环境,但外部环境不能访问内部环境中的任何变量和函数。

4.2.1 延长作用域链

执行环境的作用域链总共只有两种--全局和局部(函数),但是还是有其他办法来延长作用域链。

  1. try-catch语句的catch 块
  2. with 语句

4.2.2 没有块级作用域

if(true){
	var color = "red"
}
console.log(color)   //打印出来“red”

**if语句中的变量声明会将变量添加到当前的执行环境 ** 而

if(var i=0 ; i<10 ;i++){

}
console.log(i)   //打印出来10

for语句创建的变量i即使在for循环执行结束后,也依旧会存在于循环外部的执行环境中

  1. 声明变量

  2. 查询标识符

4.3 垃圾收集

具有自动垃圾收集机制。

4.3.1 标记清楚

JavaScript中最常用的垃圾收集方式是标记清除(mark-and-sweep)

4.3.2 引用计数

另一种不常见的垃圾收集方式是引用计数(reference counting)

4.3.3 性能问题

4.3.4 管理内存