4.变量、作用域和内存
4.1.基本类型和引用类型
4.1.1.动态的属性
-
不能给基本类型的值添加属性
var name = 'ming'; name.age = 27; alert(name.age); // undefined
4.1.2.复制变量值
- 基本类型复制值(栈内存)
- 引用类型复制地址(栈内存)
4.1.3.传递参数
-
按值传递
-
传递值类型
-
传递引用类型
// eg1 function setName(obj) { obj.name = "ming"; } var person = new Object(); setName(person); alert(person.name); // ming // eg2 虽然在函数内部修改了参数值,但原始的引用保持不变 function setName(obj) { obj.name = "ming"; obj = {name: "mei", age: 12} } var person = new Object(); setName(person); alert(person.name); // ming
4.1.4.类型检测
- typeof
- 确定一个变量是String, Number, Boolean, undefined 还是 Object
- instanceof
- 确定是什么类型的对象, Function ? Array ? RegExp ?
- 检测基本类型会返回false, 因为基本类型不是对象
4.2.执行环境及作用域,作用域链
-
每个执行环境都有一个与之关联的变量对象
-
全局执行环境是window对象 (关闭网页或浏览器时才被销毁)
-
每个函数都有自己的执行环境,当执行流进入一个函数时,函数的环境就会被推入一个环境栈中,而在函数执行之后,栈将其环境弹出,把控制权返回给之前的执行环境
-
当代码在一个环境中执行时,会创建变量对象的一个作用域链。 作用域链的用途是保证对执行环境有权访问的所有变量和函数的有序访问。
-
作用域链的前端始终是当前执行的代码所在的环境的变量对象。如果这个环境是函数,则将其活动对象作为变量对象。活动对象在最开始时只包含一个变量,即arguments对象(此对象在全局环境中是不存在的)。作用域链中的下一个变量来自包含环境,而再下一个变量对象则来自下一个包含环境。这样一直延续到全局执行环境,全局执行环境的变量对象始终都是作用域链中的最后一个对象。
-
标示符解析是沿着作用域链一级一级地搜索标示符的过程。
-
var color = "blue"; function changeColor() { var anotherColor = "red"; function swapColor() { var tempColor = anotherColor; anotherColor = color; color = tempColor; // 这里可以访问color, anotherColor和tempColor } // 这里可以访问color, anotherColor但不能访问tempColor } // 这里只能访问color changeColor();
4.2.1.延长作用域链
- with块内部的变量会被添加到外部的执行环境中
4.2.2.没有块级作用域
- if、for
- 未声明而直接初始化会放到全局作用域中,严格模式下不允许
4.3.垃圾收集*
4.3.1.标记清除
4.3.2.引用计数
4.3.3.性能问题
- 动态修正各种元素的内存回收临界值
4.3.4.管理内存
-
var person = {name: "ming", age: 12}; console.log(name); // 手工解除name的引用 person = null;