变量、作用域和内存问题

JavaScript变量松散的类型的本质,决定了它只是在特定的时间用于保存特定值的一个名字而已。而不存在定义某个变量必须保存何种数据类型值的规则,变量的值和保存的数据类型会随着脚本的生命周期改变而改变。

1、基本类型和引用类型

5种基本数据类型:String、Number、Boolean、Null、Undefined。就是简单的数据段

对象Object是引用数据类型,由多个值构成的对象。

1.1 动态的属性

var person=new Object();
person.name="zhanghuanyao";
alert(person.name);//"zhanghuanyao"
var person="zhanghuanyao";
person.name="huanyao";
alert(person.name);//undefined

这说明只能给对象也就是 所谓的引用类型添加对象,不能给基本的数据类型添加属性。

1.2 复制变量值(按值传递),一定是按值传递的

javascript中的所有函数的参数传递都是按值传递的。

function add(num){
num+=20;
return num;
}
var count=20;
console.log(add(count));//30
console.log(count);//20,传到函数中的是数值,并不是引用,因此按值传递的

使用数值等数据段的基本类型比较好解释函数中的参数是按照值传递的。再给个例子是针对引用类型的

function setName(obj){
   obj.name="zhang";
}
var z=new Object();
z.name="huan";
z.age=99;
 setName(z);
alert(z.name+z.age);//“zhang99”这好像给人的感觉就是按引用传递,但是实际上就是按照的是z这个指针的值传递的,就是把z的指针值复制了一个给了obj,
                      这样两个人就指向了同一个对象
function setName(obj){
     obj.name="zhang";
     obj=new Object();
     obj.name="huanyao";
}
var person=new Object();
setName(person);
alert(person);//"zhang",这就说明了obj获得的就是我person指针的一个复制值,obj一旦指针值变化了,
              //并不影响person的指向,所以不是按照引用地址的传递,而是就是按值传递。

1.3 typeof()和instanceof()

var a=2;
var s="zhang";
var b=true;
var c;
var d=null;
var f=new Object();
alert(typeof(a))//number
alert(typeof(s))//string
alert(typeof(b))boolean;
alert(typeof(c))//undefined
alert(typeof(d))//object;
alert(typeof(e))//object;
alert(a instanceof Number)//false;
alert(s instanceof Number)//false;

2 执行环境和作用域

执行环境是JavaScript中最重要的一个概念。

全局执行环境是最外围的一个执行环境,在Web浏览器中,全局执行环境被认为是window的对象,因此所有的全局变量和函数都是作为window对象的属性和方法创建的。全局执行环境直到应用程序退出——如关闭网页或者浏览器——才会被销毁。

每个函数都有自己的执行环境。

var color="blue";
function changColor(){
if(color="blue")
{
   color="red";
}
else{
color="blue";}}
changeColor();
alert("color is now:"+color);//red,这里延伸一下就发现了,当空参函数时,没有什么参数按照值传递,而是直接沿着作用域链找,函数中的变量变化会反应到全局变量
                             //中。

沿着作用域链,外部环境的访问不到里面的,内部环境的可以向外访问,如:

var color="blue";
function changColor(){
var anotherColor="red";
function swapColor(){
var temp=anotherColor;
   anotherColor=color;
  color=temp;//这里可以访问的变量是color,temp,anotherColor}//这里只能访问anotherColor,color}//这里只能访问color

2.2 没有块级作用域(这点很奇怪,循环语句做完计算以后,居然循环体中的变量都会添加到当前的执行环境中)

if(true){
var color="blue";
}
alert(color)//"blue"
for(var i=0;i<10;i++)
{
     dosomething(i);
}
alert(i);//10,循环体结束居然还存在着,把i添加到了当前的执行环境中

2.3作用域中的变量声明

function add(num1,num2){
   var sum=num1+num2;
   return sum;}
var result=add(10,20);
alert(sum);//由于sum在局部的执行环境中,外部环境是访问不到的,另外add()执行结束以后就弹栈了,找都找不到sum。
function add(num1,num2){
   sum=num1+num2;
   return sum;}
var result=add(10,20);
alert(sum);//30一旦在初始化sum的时候没有使用关键字var,就会调用完add()函数以后,被留在全局变量中,使得所有的其他代码可以继续访问它。

3 垃圾回收机制

我们来分析一下函数中局部变量的生命周期。局部变量只在函数执行过程中存在,在这个过程中,会为局部变量在栈或者堆内存上分配相应的空间,以便存储他们的值。然后在函数中使用这些变量,直到函数之间执行结束。此时,局部变量就没有存在的必要,因此可以释放它们的内存以供将来使用。

垃圾收集器必须跟踪哪个变量是否还有存在的必要,对于不再用的变量打上标记,以备将来收回其占用的内存。

3.1标记清除

javascript中最常用的垃圾收集方式是标记清除。当变量进入环境(例如在函数中声明一个变量的时候),就将这个变量标记为“进入环境”。当变量离开环境时,将其标记为“离开环境”.最后,垃圾收集器完成内存清除,销毁那些带离开环境标签的变量并且回收它们所占用的内存。

注意解除一个值的引用(object=null),并不意味着自动回收该值所占用的内存,解除引用的真正作用是让值脱离执行环境,以便垃圾收集器下次运行时将其回收。


4小结

Undefined、Null、String、Number、Boolean五种基本数据类型,就是简单的数据段

引用类型值和基本类型值具有以下特点:

1、基本类型值在内存中占据固定大小的内存空间,被保存在栈内存中;

2、从一个变量向另一个变量复制基本数据类型的值,就只会创建这个值的一个副本

3、引用类型的值是对象,保存在堆内存中;

4、包含引用类型值的变量实际上并不是对象本身,而是一个指向该对象的指针

5、从一个变量向另一个变量复制引用类型的值,复制的是指针,因此两个变量最终都指向同一个对象;

6、确定一个是哪种基本类型可以使用typeof(变量)操作符。而确定一个值是哪种引用类型可以使用instanceof操作符

7、全局环境只能访问全局环境中定义的变量和函数,而不能直接访问局部环境中的任何数据

8、离开作用域的值将被自动标记为可以回收,因此将在垃圾收集期间被删除

9、标记清除是目前主流的垃圾收集算法,这种算法的思想是给当前不使用的值加上标记,然后再回收其内存





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值