JavaScript第四章学习
ECMAScript变量可能包含两种不同数据类型的值:基本类型值和引用类型值。
基本类型值:简单的数据段。
引用类型值:多种值构成的对象。
5种基本类型值:
Undefined,Boolean,Null,Number,String
1:动态属性
1:创造一个变量并为其赋值。例:
var A=new Object();
A.name = "useful";
alert(A.name); //"useful"
注:不可为基本类型的值添加属性,例:
var A="Nicholas";
A.age=27;
alert(A.age); //Undefined
2:复制变量值
如果从一个变量向另一个变量复制基本类型值和引用类型值,会在变量对象上创造另一个新值,然后将该值复制到新变量分配的位置上,例:
var A1=1;
var A2=A1;
注:上述中A1中的1与A2的1是完全独立的。
又一例:
var A1=new object();
var A2=A1;
A1.use="useful";
alert(A2.use); //"useful"
如上述,A1保存了一个对象的新实例。然后该值被复制到A2中,即:A1和A2都指向同一个变量。
该值的副本(A2)实际上是一个指针。
3:传递参数
例:function B(num)
{num+=10;
return num;}
var A=10;
var C=B(A);
alert(A); //10
alert(C); //20
注:如上述:num实际上是函数的局部变量。在调用此函数时,变量A作为参数被传递给函数,数字10被复制给num并被使用。num与A没有关系,只是数值相同
引用类型的传递
首先,它传递时是按照引用来复制的,就是把指针复制一份给局部变量,让它也指向堆内存中的那个对象,于是,局部变量对对象进行新增属性方法同样也会影响到其他引用这个对象的变量。但这不能说它是按引用传递,因为假如要在函数内部修改局部变量的引用地址,那么是不会影响传进来的那个变量的引用地址的,这里两个例子:
function A(use)
{ use.name="B";
}
var siyun =new object()
A(siyun);
alert(siyun.name); //"B"
function A(use)
{
use.name="B";
use=new object();
use.name="C"
}
var siyun=new object();
A(siyun);
alert(siyun.name); //"B"
上面代码定义了siyun变量,并指向堆中一个对象,接着把值传给了A,使A也指向堆中那个对象,接着在函数中新增name属性,这时,也会让siyun新增name属性,值为“B”,因为他两都引用同一个对象。接着函数又为use重新引用了新的对象,然后又为这个对象新增name属性,这时再看看alert(siyun.name),输出的仍然是B,而不是C,这是因为,引用新的对象相当于赋了新的值,这个赋值不会影响siyun变量的值,即siyun变量原本对原本对象的引用,这是不会改变的,所以说这也是一种按值传递。
3:检测类型
可用typeof来检测是不是基本数据类型。例:
var A=2;
alert(typeof A); //number
2:执行环境及作用域
每个函数都有自己的执行环境。例:
var A="siyun";
function A1(){
var B="lisiyun";
function A2(){
var C="I love you";
B=A;
A=C;
}
A2();
}
A1;
上述例子涉及三个执行环境:全局环境,A2()的局部环境和A1()的局部环境。上述环境中,A2()函数可访问A,B,C三个变量,但全局环境与A1()的局部环境均无法访问C。
4:延长作用域链?
1:使用下列语句可以延长作用域链
1:try-catch语句的catch块
2:with语句
例:
function A(){
var A1="?debug=true";
with(lisiyun){
var A2=A1+siyun;
}
return A2;
}
上述例子中,with接收的是lisiyun对象,A2也能成为函数执行环境的一部分,可以作为函数的值被返回。
注:
在使用if语句与for语句时,例:
if(true){
var A="siyun";
}
alert(A); //"siyun"
if语句与for语句中的变量(如:for(i=1;i<10:;i++)中的i)仍然会存在于循环外部的执行环境中。
2:声明变量
在局部环境中,若初始化变量没有用var声明,则该变量会自动添加到全局变量。例:
function A(a,b){
siyun=a+b;
return siyun;
}
var B=A(10,20); //30
alert(siyun); //30
上述例子中,siyun是A(a,b)环境中的变量,但仍然客可被添加到全局环境中。
3:查询标识符
例:
var color+"blue";
function getcolor()
{
return color;
}
alert(getcolor()); //"blue"
在上述例子中,调用getcolor()会引用color,其会自动搜索color的值,(优先在自身的局部函数中搜索)
4:垃圾搜集
下列是标识无用变量的策略。(JavaScript能自动清除垃圾,但也需标识出无用变量)
3.1 标记清除
当变量进入环境则将该变量标记为“进入环境”,当变量离开环境则标记为“离开环境”。而它是如何标记的我们不用管。
在垃圾收集器运行时,把内存中所有变量都加上标记,再把被引用的变量的标记去除,而在此之后又被加上标记的变量即为即将删除的变量。
到2008年为止,IE、Firefox、Opera、Chrome和 Safari都采用标记清除方式。
3.2 引用计数
这种方式不太常见,
工作原理是:跟踪记录每个值被引用的次数,当声明了一个变量并将一个引用类型值赋给该变量时,则这个值的引用次数就是 1。 如果同一个值又被赋给另一个变量,则该值的引用次数加 1。相反,如果包含对这个值引用的变量又取 得了另外一个值,则这个值的引用次数减 1。当这个值的引用次数变成 0时,就可以将其内存空间回收了。
3.3 管理内存
分配给 Web 浏览器的可用内存数量通常要比分配给桌面应用程序的少,这样做是为了放置Web耗尽系统全部内存而导致系统崩溃,因此确保占用最少的内存可以让页面有更好的性能,而优化内存占用的最佳方式,就是为执行 中的代码只保存必要的数据。一旦数据不再有用,最好通过将其值设置为 null 来释放其引用——这个 做法叫做解除引用
例:function A(useful){
var B=new object();
B.something=useful;
return B;
}
var C=A("siyun");
C=null;
例中,全局变量C被手动解除引用