javascript 高级程序设计(二)

第 4 章 变量、作用域和内存问题
4.1 基本类型和引用类型的值
4.1.1 动态的属性
定义基本类型值和引用类型值的方式是类似的:创建一个变量并为该变量赋值。

var person = new Object();
person.name = "Nicholas";
alert(person.name); //"Nicholas" 

但是,我们不能给基本类型的值添加属性,尽管这样做不会导致任何错误。比如:

var name = "Nicholas";
name.age = 27;
alert(name.age); //undefined

为字符串 name 定义了一个名为 age 的属性,为该属性赋值 27。但在下一
行访问这个属性时,发现该属性不见了。这说明只能给引用类型值动态地添加属性,以便将来使用。

4.1.2 复制变量值
从一个变量向另一个变量复制基本类型的值,会在变量对象上创建一个新值,然后把该值复制到为新变量分配的位置上。

var num1 = 5;
var num2 = num1; 

4.1.3 传递参数
在向参数传递基本类型的值时,被传递的值会被复制给一个局部变量(即命名参数,或者用ECMAScript 的概念来说,就是 arguments 对象中的一个元素)。

function addTen(num) {
 num += 10;
 return num;
} 
var count = 20;
var result = addTen(count);
alert(count); //20,没有变化
alert(result); //30 

4.1.4 检测类型
typeof 操作符是确定一个变量是字符串、数值、布尔值,还是 undefined 的最佳工具

var s = "Nicholas";
var b = true;
var i = 22;
var u;
var n = null;
var o = new Object();
alert(typeof s); //string
alert(typeof i); //number
alert(typeof b); //boolean
alert(typeof u); //undefined
alert(typeof n); //object
alert(typeof o); //object 

4.2 执行环境及作用域

var color = "blue";
function changeColor(){
 if (color === "blue"){
 color = "red";
 } else {
 color = "blue";
 }
}
changeColor();
alert("Color is now " + color); 

4.2.1 延长作用域链
虽然执行环境的类型总共只有两种——全局和局部(函数)
 try-catch 语句的 catch 块;
 with 语句。
这两个语句都会在作用域链的前端添加一个变量对象。对 with 语句来说,会将指定的对象添加到作用域链中。对 catch 语句来说,会创建一个新的变量对象,其中包含的是被抛出的错误对象的声明。
下面看一个例子。

function buildUrl() {
 var qs = "?debug=true";
 with(location){
 var url = href + qs;
 }
 return url;
}

4.2.2 没有块级作用域

  1. 声明变量
    使用 var 声明的变量会自动被添加到最接近的环境中。 在with 语句中,最接近的环境是函数环境
function add(num1, num2) {
 var sum = num1 + num2;
 return sum;
}
var result = add(10, 20); //30
alert(sum); //由于 sum 不是有效的变量,因此会导致错误

以上代码中的函数 add()定义了一个名为 sum 的局部变量,该变量包含加法操作的结果。虽然结果值从函数中返回了,但变量 sum 在函数外部是访问不到的。如果省略这个例子中的 var 关键字,那么当 add()执行完毕后,sum 也将可以访问到:

function add(num1, num2) {
 sum = num1 + num2;
 return sum;
}
var result = add(10, 20); //30
alert(sum); //30 
  1. 查询标识符
    当在某个环境中为了读取或写入而引用一个标识符时,必须通过搜索来确定该标识符实际代表什么
    通过下面这个示例,可以理解查询标识符的过程:
var color = "blue";
function getColor(){
 return color;
}
alert(getColor()); //"blue" 

如果局部环境中存在着同名标识符,就不会使用位于父环境中的标识符,如下面的例子
所示:

var color = "blue";
function getColor(){
 var color = "red";
 return color;
}
alert(getColor()); //"red" 

任何位于局部变量 color 的声明之后的代码,如果不使用 window.color 都无法访问全局 color变量。

变量查询也不是没有代价的。很明显,访问局部变量要比访问全局变量更快,因
为不用向上搜索作用域链。JavaScript 引擎在优化标识符查询方面做得不错,因此这
个差别在将来恐怕就可以忽略不计了。

4.3 垃圾收集
JavaScript 具有自动垃圾收集机制,也就是说,执行环境会负责管理代码执行过程中使用的内存。
函数中局部变量的正常生命周期,局部变量只在函数执行的过程中存在。

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

4.3.2 引用计数
另一种不太常见的垃圾收集策略叫做引用计数(reference counting)。
4.3.3 性能问题
4.3.4 管理内存

4.4 小结
JavaScript 变量可以用来保存两种类型的值:基本类型值和引用类型值。基本类型的值源自以下 5种基本数据类型:Undefined、Null、Boolean、Number 和 String。基本类型值和引用类型值具有以下特点:
 基本类型值在内存中占据固定大小的空间,因此被保存在栈内存中;
 从一个变量向另一个变量复制基本类型的值,会创建这个值的一个副本;
 引用类型的值是对象,保存在堆内存中;
 包含引用类型值的变量实际上包含的并不是对象本身,而是一个指向该对象的指针;
 从一个变量向另一个变量复制引用类型的值,复制的其实是指针,因此两个变量最终都指向同一个对象;
 确定一个值是哪种基本类型可以使用 typeof 操作符,而确定一个值是哪种引用类型可以使用instanceof 操作符。

所有变量(包括基本类型和引用类型)都存在于一个执行环境(也称为作用域)当中,这个执行环境决定了变量的生命周期,以及哪一部分代码可以访问其中的变量。
 执行环境有全局执行环境(也称为全局环境)和函数执行环境之分;
 每次进入一个新执行环境,都会创建一个用于搜索变量和函数的作用域链;
 函数的局部环境不仅有权访问函数作用域中的变量,而且有权访问其包含(父)环境,乃至全局环境;
 全局环境只能访问在全局环境中定义的变量和函数,而不能直接访问局部环境中的任何数据;
 变量的执行环境有助于确定应该何时释放内存。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值