您的位置:首页 > Web前端 > JavaScript

JavaScript高级程序设计学习笔记——第4章 变量,作用域和内存问题

2013-05-17 16:05 337 查看
2013-5-17 | 发布者:www.sealiu.tk

我的笔记:

1,ECMAScript 变量可能包含有两种不同的数据类型的值:基本类型值和引用类型值。基本类型值指的是简单的数据段,而引用类型值指那些可能由多个值构成的对象;基本类型 值:(undefined,null,boolean,number,string),引用类型值是保存在内存中的对象;

1.1 添加属性:

不能给基本类型的值添加属性,尽管这样做不会导致任何错误;

var name="Nicholas";

name.age=27;

alert(name.age); //undefined

但是引用类型的值(对象)就可以;

var person=new Object();

person.name="Nicholas";

alert(person.name); //"Nicholas"

1.2 复制:

如果从一个变量向另一个变量复制基本类型的值,会在变量对象中创建一个新值;

当从一个变量向另一个变量复制引用类型的值时,同样会将存储的变量对象中的值复制一份放到新变量分配的空间中。不同的是,这个值的副本实际上是一个指针,指向存储在堆中的一个对象。复制结束后两个变量实际将引用同一个对象

1.3 传递参数:

向参数传递基本类型的值时:函数外部的值复制给函数内部的参数,就和吧值从一个变量复制到另一个变量一样;看下面的代码:

function addTen(num){

num+=10;

return num;

}

var count=20;

var result=addTen(count);

alert(count); //20,没有变化

alert(result); //30

//这里的addTen( )有一个参数num,而参数的实际是函数的局部变量。在函数内部参数num被加上了10,但这一变化不会影响到函数外部的count变量。这是按值传递;如果是按引用传递的话,那么变量count的值也将变成30;

如果使用对象,也是按值传递,但是和上面会有所不同,看下面的代码:

function setName(obj){

obj.name="Nicholas";

}

var person=new Object( );

setName(person);

alert(person.name); //"Nicholas"

//上面代码中创建了一个对象,并保存在了person变量中,传递到setName()函数中就复制给了obj;在函数内部obj和person引用的是同一个对象。所以当函数内部为

obj添加name属性后,函数外部的person也将有变化;因为person所指向的对象在内存中只有一个而且是全局变量。但是这些不足已说明这个对象是按值传递的,看下面的代码:

function setName(obj){

obj.name="Nilcholas";

obj=new Object();

obj.name="Greg";

}

var person=new Object();

setName(person);

alert(person.name); //"Nilcholas"

//添加了两行代码:一行为obj重新定义了一个对象,另一行代码为对象定义了一个带有不同值的name属性。如果person是按引用传递的,那么person就会被修改为指向其name属性值为“Greg”的新对象。结果证明这是错的!

1.4 检测类型

typeof 操作符(第3章),typeof是确定一个变量时字符串,数字,布尔值,还是undefined的最佳工具。但是在检测应用类型的值的时候,这个操作符用 处不大。通常,我们并不是想知道某个值时对象,而是想知道是什么类型的对象。为此ECMAScript提供了instanceof操作符

语法:result=variable instanceof constructor

举例:

alert(person instanceof Object); //变量person是Object么?

alert(person instanceof Array); //变量person是Array么?

alert(person instanceof RegExp); //变量person是RegExp(正则表达式)么?

[b]2[/b].执行环境及作用域,和C++语言的变量作用域类似。每个函数都会有自己的执行环境(有时也称为“环境”)。

全局环境,局部环境(每个函数的),在全局环境定义的变量是全局变量(可以在程序的任何地方访问),在局部环境定义的变量是局部变量(只能在定义它的那个局部环境中访问)。

2.1 延长作用域链的两个方法:

try-catch语句的catch块;
try
{
// 可能会引发错误的一些代码
}
catch (err:Error)
{
// 用于响应错误的代码
}
finally
{
//其余需要运行的代码。
}

将有可能产生错误的语句括在一起,放入try语句块。如果在try语句块中发生异常,FlashPlayer会创建一个错误对象,并将该Error对象派发至第一个可用的catch块。

catch
语句快提供对错误的处理。如果没有try语句,或者try语句没有出现错误,则catch语句不会被引发。如果在try语句块的其中某个 语句中检测到错
误,则会执行附加到该try语句的catch语句。catch语句可以并列使用,即在一个try语句块之后,存在多个catch语句块,以 处理不同的错
误对象。

with语句


在 With 语句块中,凡是 JavaScript 不识别的属性和方法都和该语句块指定的对象有关。With 语句的语法格式如下所示:

With Object {
Statements
}
对象指明了当语句组中对象缺省时的参考对象,这里我们用较为熟悉的 Document 对象对 With 语句举例。例如 当使用与 Document 对象有关的 write( )或 writeln( )方法时,往往使用如下形式:
document.writeln(”Hello!“)

果需要显示大量数据时,就会多次使用同样的 document.writeln()语句,这时就可以像下面的程序那样,把所有以 Document
对象为参考对象的语句放到With 语句块中,从而达到减少语句量的目的。下面是一个With 语句使用的例子:

<html>
<head>
<title>JavaScript Unleashed</title>
</head>
<body>
<script type="text/javascript">
with(document){
write("您好 !");
write("<br>这个文档的标题是 : \"" + title + "\".");
write("<br>这个文档的 URL 是: " + URL);
write("<br>现在您不用每次都写出 document 对象的前缀了 !");
}

</script>
</body>
</html>


这样,您在使用 document 的方法和属性时就可以去掉 Document 前缀。


2.2 JS没有块级作用域,不同于C,C++,Java

if(true){

var color="blue";

}

alert(color); //blue

但C,C++或Java这种有块级作用域的语言来说,color会在if语句执行完毕后被销毁。但是JavaScript不会。

如果初始化变量时没有使用var声明,该变量就是全局变量。否则是局部变量;

function add(num1,num2){
var sum=num1+num2;
return sum;
}

var result=add(10,20);    //30
alert(sum);        //由于sum不是有效的变量,出错


function add(num1,num2){
sum=num1+num2;
return sum;
}

var result=add(10,20);    //30
alert(sum);                     //30


查询标识符的方向是从局部环境向上到全局环境(搜索过程冲作用域链的前端开始,向上逐级查询给定名字匹配的标识符)

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

//=====================

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


3. 垃圾收集

JavaScript具有自动垃圾收集机制,而在C++语言中需要手工跟踪内存的使用情况。

JS垃圾收集的两种方式:

标记清除

应用计数

由于分配给Web浏览器的可用内存数量通常要比非配给桌面应用程序的少,所以确保占用最少内存让页面获得更好的性能,可以通过手工接触引用(将其值设置为null)来释放其引用。

function creatPerson(name){
var localPerson=new.Object();
localPerson.name=name;
return localPerson;
}
var globalPerson=creatPerson("Nicholas");
//手工解除globalPerson的引用
globalPerson=null;


解除引用的作用真正作用是让值脱离执行环境,以便垃圾收集器下一次运行时将其回收。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: