Javascript高级程序设计——11.变量、作用域、缓存

1、变量及作用域

(1)ECMAScript的两种数据类型:基本类型、引用类型值

a、基本类型:栈内存中简单的数据段(完全保存在内存中的一个位置)

b、引用类型:堆内存中的对象(保存实际上只是一个指针,该指针指向内存中的另一个位置,该位置保存对象)

当把一个值赋值给变量时,解析器必须确定是基本类型,还是引用类型

a、基本类型(5种):undefined、null、boolean、string、number

特点:有固定大小的空间,值保存在栈空间

注意:某些语言中,字符串string以对象的形式来表示,被认为引用类型,ECMAScript放弃该传统

b、引用类型:Object{}类型

特点:内存大小不固定,值保存在堆内存空间中

操作:当查询引用类型的变量时,先从栈中读取内存地址,再通过地址找到堆中的值,即按引用访问。


不同点:基本类型按值访问,引用类型按引用访问


(2)动态属性

a、定义类型值方式为:创建一个变量为该变量赋值,

var box=new Object();  //{}
box.name=‘zhao’;    //新建一个属性
alert(box.name);


b、基本类型

var box='zhao' ;  //基本类型值,是字符串;
box.age=28;
alert(box.age);  //undefined;


由于上述代码不引用类型,所以无法输出


(3)复制变量的值

基本类型:值本身

引用类型:复制为地址

a、基本类型

var box='Lee';    //保存在box'Lee'
var box2=box;  //栈内润再生成一个‘box2 'Lee'’
box2='kk';   //基本类型保持独立,box不会进行复制
alert(box);     //Lee
alert(box2);   //kk


b、引用类型

var box=new Object();    //创建一个引用类型;
box.name='Lee';
var box2=box;
alert(box.name);      //‘Lee’
alert(box2.name);  //Lee

上述代码中,由于是按照地址传递,所以box与box2是相同的,即当box.name变化时,box2.name也会变化。



(4)传递参数

a、基本类型(按值传递)

function box(num){
num+=10;
return num;
}
var num=50;
alert(box(num));    //60
alert(num);           //50
//(若按引用传递,那么函数量的num会成为类似于全局变量,也就是说,最后会打印60)


注意:Javascript中不会按照引用传递,所以不可能打印出60,但在php文件中可以按引用传递,即为全局变量

demo1.php(按引用传递)

';
echo num;     //60
?>


b、引用传递(传参引用参数)

function box(obj){       //按值传递参数,传递一个引用类型的参数,而不是按值传参,
obj.name='Lee';
var obj=new Object();     //所以,js没有按引用传递参数功能,不能把传递引用参数当成引用传参
obj.name='kkk';
}
var obj=new Object();
box(obj);
alert(obj.name);

结果:Lee

解析:若按引用传参,即结果为“kkk”,但是新建的object对象,表现的不能被外界看到。


易混点——按引用传递和传递引用类型

这两个是不同的概念:

(1)按引用传递:函数中变量为全局变量,在外部也可以访问

(比如php中,必须在参数前加&号表示按引用传递)

(2)传递引用类型:函数中变量为局部变量,在外部不可以访问


总结:ECMAScript中没有按引用传递,只能是局部变量,在PHP中可以实现。


(5)检测类型

A——基本类型

必须采用typeof运算符进行检测,但对于引用类型typeof就不可以,若不是检测是否为对象,而是检测是何种类型的对象,采用instanceof运算符

function box(obj){       //按值传递参数,传递一个引用类型的参数,而不是按值传参,
obj.name='Lee';
var obj=new Object();     //所以,js没有按引用传递参数功能,不能把传递引用参数当成引用传参
obj.name='kkk';
}
var obj=new Object();
box(obj);
alert(obj.name);

总结:数组array,空对象null,正则表达式regexp都表示的是“对象”;


B——引用类型

案例5-1:用instanceof运算符检测引用类型

var box1=[1,2,3];
alert(instanceof Array);    //是否为数组,返回true;
var box2={};
alert(instanceof Object) ;  //是否为对象,返回true;
var box3=/g/;
alert(instanceof RegExp);  //是否为正则表达式,返回false;


区别:typeof运算符、instanceof运算符

(1)typeof——检测基本类型,一般返回基本类型(如object、number、string、null、boolean、undefined)

(2)instanceof——检测引用类型,检测某一个变量是否为某一个数据类型,通常返回的是true或false

(注意:当用instanceof检测基本类型时,会返回false,见案例4-2)

案例5-2:

var box=String();
alert(box instanceof String);   //检测box是否为对象,返回false(由于string为基本类型)


若想返回true,即需要用基本类型方式来创建对象,见案例4-3

案例5-3:

var box=new Object('Lee');
alert(box instanceof String);   //返回true(由于有new关键字)


注意——

对基本类型而言,(1)若有new关键字创建对象并检测时,用instanceof运算符

        (2)若无new关键字直接创建对象时,用typeof运算符


(6)执行环境及作用域

a、对于全局变量,位于最外围,属于window属性

b、对于全局函数,位于最外围,属于window的方法

案例6-1:

var box='blue';
function setBox(){
	alert(window.box);        //全局变量即window的属性
}
window.setBox();               //全局函数即window的方法;


注意:当执行完所有代码后,该环境被销毁,保存在其中的变量也将随之被销毁。


c、作用域“全局作用域window”、“局部作用域”

c-1:若局部子函数中有var,即为局部变量;若无var,即可以取代之前的全局变量

	var box='Lee';
	function setBox(){
		//var box='red';  
		 //局部变量,范围在setBox中,出去就被销毁,结果为“Lee”
		box='red';
		//box为全局变量,结果为“red”
	}
	setBox();
	alert(box);


(2)当传参数时,也为局部变量

	var box='Lee';
	function setBox(box){    //通过传参,也是局部变量,作用与在setBox中;
		alert(box);
	}
	setBox('red');
	alert(box);

结果:仍为“Lee”,由于该参数box在setBox()函数中,“red”参数进去执行完毕即被销毁,并没有传递到window下。


(3)当函数中包含着函数,即被包含的函数也是局部变量

var box='Lee';
function setBox(){
	function setColor(){         //setColor()执行作用域在setBox()中;
		//var b='kkk';           //变量b作用域位于setColor()中
		//alert(b);
		return 123;
	}
}
alert(window.setBox());    //123


(6)没有块级作用域

块级作用域,即诸如if语句等花括号封闭的代码块,

所以,支持条件判断莱斯你故意变量。

案例1:if、for语句没有封闭作用域的功能,即可被外围访问,window下的全局变量。

if(true){
	var box='Lee';
}
alert(window.box);


案例6-2:var关键字在函数中使用

function box(){
	//var num=10;     //有var,在函数体内声明变量,表示局部变量。
	num=10;            //无var,在函数体内表示全局变量
}
box();
alert(num);


(7)变量查询

向上查询搜索的功能

var box='blue';
function getColor(){
	var box='red';
	return box;
}
alert(getColor());

结果:返回red,由于在getColor()函数中已经存在box对象,就不必向外部window进行上一级搜索。


2、内存问题

(1)Javascript有自动垃圾收集功能,也就是说,执行环境会负责管理代码执行过程中使用的内存。

(2)Javascript最常用的垃圾收集方式:标记清除。

(垃圾收集器会在运行的时候给存储在内部变量加上标记,会去掉环境中正在使用变量的标记,而没有被去掉的标记视为准备删除的变量,最后当垃圾收集器完成内存清理工作,销毁那些带标记的值并回收他们所占用的内存空间)。

(3)优化内存的性能方法:一旦数据不再使用,将其设置为null来释放引用,即“解除引用”,

适用于大多数全局变量和全局对象

案例2-1:null解除引用的案例

var box={};
box.name='Lee';
alert(box.name);   //Lee


box=null;    //销毁引用,等待清理;
alert(box);      //null


但是,若为window的时候,不可以解除引用

案例2-2:

var box='Lee';
alert(window.box);  //Lee
window=null;
alert(window);     //Lee

解析:由于window不可能被设置为null。


你可能感兴趣的:(Javascript,Javascript,web前端复习+面试)