JavaScript 变量、作用域和内存问题

来源:互联网 发布:近年来重庆物流数据 编辑:程序博客网 时间:2024/05/01 04:34

1.基本类型和引用类型的值

    JavaScript变量可能包含两种不同数据类型的值:基本类型值和引用类型值。

基本类型值有五种:undefined,null,boolean,number,string。这五种数据类型是按值访问的,因此可以操作保存在变量中的实际的值。

    引用类型的值是保存在内存中的对象。JavaScript不允许直接访问内存中的位置,在操作实际对象时,实际上是操作对象的引用而不是实际的对象。因此,引用类型的值是按引用访问的。

    我们不能给基本类型的值添加属性。比如:

    var name = "Liming";

    name.age = 22;

    alert("name.age");//undefined


2.关于复制变量值

例:var num1 = 5;

    var num2 = num1;

    num1和num2的值都是5,但是两者是完全独立的,num2中的5只是num1中的一个副本。这两个变量可以参与任何操作而不会相互影响。

    当一个变量向另一个变量复制引用类型的值时,同样也会将存储在变量对象中的值复制一份放到为新变量分配的空间中。不同的是,这个值的副本实际上是一个指针,而这个指针指向存储在堆中的一个对象。改变其中一个变量,就会影响到另一个变量。


3.关于传递参数

    访问变量有按值和引用两种方式,但是参数传递只能按值传递。

例:function addTen(num){

num+=10;

return num;

}

var count = 20;

var result = addTen(count);

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

alert(result);//30


    num是addTen()函数的参数,而参数实际上是函数的局部变量。count作为参数被传递给函数,在函数中被复制给参数num,然后被加上了10。这不会影响函数外部的count变量。


例:function setName(){

obj.name = "Liming";

obj = new Object();

obj.name = "Greg";

}

var person = new Object();

setName(person);

alert(person.name);//Liming


    如果person是按引用传递的,那么person就会自动被修改为指向其name属性值为“Greg”的新对象。但alert出来的还是Liming,说明即使在函数内部修改了参数的值,但原始的引用仍然保持未变。

    实际上,当在函数内部重写obj时,这个变量引用的就是一个局部变量了,这个局部对象会在函数执行完毕后立即被销毁。


4.关于作用域

    当代码在一个环境中执行时,会创建一个作用域链。全局执行环境是最外围的一个执行环境。在web浏览器中,全局执行环境是window对象。当某个执行环境中的所有代码执行完后,该环境被销毁,保存在其中的所有变量和函数定义也被销毁(全局执行环境直到应用程序退出例如关闭浏览器或网页时才被销毁)。

    回到作用域链,作用域链的前端始终都是当前执行的代码所在环境的变量对象,然后是包含外部环境,再然后是下一个包含环境,直到全局执行环境。

    每个环境都可以向上搜索作用域链,查询变量和函数名,但是不能向下搜索作用域链而进入另一个执行环境。


注意:

(1)JavaScript没有块级作用域。如:

for(var i=0; i<10; i++){

doSomething(i);

}

alert(i);//10

    对于有块级作用域的语言来说,由for语句创建的变量i只存在于循环中。但对于JavaScript,i在循环结束后仍存在于循环外部的执行环境中。

(2)如果初始化变量时没有使用var声明,该变量会自动被添加到全局变量。

(3)查询标识符

例:var color =  "blue";

       function getColor(){

return color;

}

alert(getColor());//blue

    在调用函数的过程中,会先搜索getColor()中是否包含一个名为color的标识符。如果没有找到,搜索继续到下一个变量对象(全局环境的变量对象),然后找到了color,搜索结束。在这个搜索过程中,如果存在一个局部的变量的定义,则搜索会自动停止,不再进入另一个变量对象。

0 0
原创粉丝点击