JavaScript的变量是松散类型的,可以随时转换变量类型.
4.1 基本类型和引用类型的值
-
基本类型
5个基本数据类型:
undefined/Null/Boolean/Number/String
它们是按值访问的,可以操作保存在变量中的实际的值. (直接存放在栈内存之中) -
引用类型
引用类型的值是保存在内存中的对象, 不允许直接操作对象的内存空间,实际操作是在操作对象的引用(是存放在堆内存之中,操控的是栈内存中的"指针")
4.1.1 动态的属性
定义基本类型值和引用类型值的方式是类似的:创建一个变量并为该变量赋值。但是操作有很大区别,引用类型的值,可以添加属性和方法,也可以改变或者删除属性或方法。不能给基本类型的值添加属性,虽然不会报错,但是是没有意义的。
** #当复制保存在对象的某个变量时,操作的是对象的引用。但是添加属性时,操作的是实际的对象**
4.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 延长作用域链
执行环境的作用域链总共只有两种--全局和局部(函数),但是还是有其他办法来延长作用域链。
- try-catch语句的catch 块
- 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循环执行结束后,也依旧会存在于循环外部的执行环境中
-
声明变量
-
查询标识符
4.3 垃圾收集
具有自动垃圾收集机制。
4.3.1 标记清楚
JavaScript中最常用的垃圾收集方式是标记清除(mark-and-sweep)
4.3.2 引用计数
另一种不常见的垃圾收集方式是引用计数(reference counting)