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 语句使用的例子:
这样,您在使用 document 的方法和属性时就可以去掉 Document 前缀。
2.2 JS没有块级作用域,不同于C,C++,Java
if(true){
var color="blue";
}
alert(color); //blue
但C,C++或Java这种有块级作用域的语言来说,color会在if语句执行完毕后被销毁。但是JavaScript不会。
如果初始化变量时没有使用var声明,该变量就是全局变量。否则是局部变量;
查询标识符的方向是从局部环境向上到全局环境(搜索过程冲作用域链的前端开始,向上逐级查询给定名字匹配的标识符)
3. 垃圾收集
JavaScript具有自动垃圾收集机制,而在C++语言中需要手工跟踪内存的使用情况。
JS垃圾收集的两种方式:
标记清除
应用计数
由于分配给Web浏览器的可用内存数量通常要比非配给桌面应用程序的少,所以确保占用最少内存让页面获得更好的性能,可以通过手工接触引用(将其值设置为null)来释放其引用。
解除引用的作用真正作用是让值脱离执行环境,以便垃圾收集器下一次运行时将其回收。
我的笔记:
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;
解除引用的作用真正作用是让值脱离执行环境,以便垃圾收集器下一次运行时将其回收。
相关文章推荐
- JavaScript高级程序设计——第4章 变量、作用域和内存问题
- 【每天学3章,一周掌握js】第4章:变量、作用域和内存问题
- 第4章 变量、作用域和内存问题 (二)
- JavaScript高级程序设计——第4章:变量、作用域和内存问题
- 第4章:变量、作用域和内存问题
- 第4章 变量、作用域和内存问题 (一)
- 第4章 变量、作用域和内存问题(2)执行环境及作用域
- 第4章 变量、作用域和内存问题(1)基本类型和引用类型的值
- 《JavaScript高级程序设计》第4章 js中的变量、作用域和内存问题
- javascript高级程序设计笔记(第4章 变量、作用域和内存问题)
- 第4章 变量、作用域和内存问题(3)垃圾收集
- 《JavaScript高级程序设计》 - 读书笔记 - 第4章 变量、作用域和内存问题
- JS高级程序设计第三版——变量、作用域和内存问题
- JS中的变量、作用域和内存问题
- 23. 变量、作用域和内存问题
- 变量、作用域和内存问题
- 红皮书:变量、作用域和内存问题(四)
- javascript学习之变量、作用域和内存问题
- (深夜课堂)Javascript 变量、作用域和内存问题(1)
- JavaScript之变量、作用域和内存问题