欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

JavaScript高级程序设计之变量,作用域和内存问题总结

程序员文章站 2023-11-03 20:59:46
基本类型和引用类型的值 1.基本类型和引用类型的区别: (1)基本数据类型是按值访问的,可以操作保存在变量中实际的值。?引用数据类型是按引用访问的,是保存在内存中的对象,因为不...

基本类型和引用类型的值

1.基本类型和引用类型的区别:

(1)基本数据类型是按值访问的,可以操作保存在变量中实际的值。?引用数据类型是按引用访问的,是保存在内存中的对象,因为不能直接操作对象的内存空间,所以操作的是对象的引用而不是实际的对象。

(2)动态属性(只能给引用数据类型动态的添加属性):对于引用类型的值,我们可以为它添加属性和方法,也可以改变和删除此方法。我们不能给基本数据类型的值添加属性,虽然这样做不会导致错误。

(3)复制变量值:从一个变量向另一个变量复制基本数据类型的时候,会在变量对象上创建一个新值,然后把该值复制到为新变量分配的位置上,两个变量互不影响。从一个变量向另一个变量复制引用数据类型的时候,同样也会将存储在变量对象中的值复制一份放到新变量分配的空间中,不同的是,复制的值实际上是一个指针,这个指针指向存储在堆中的同一个对象,改变其中一个变量就会影响另一个变量。

(4)传递参数:ecmascript中所有函数的参数都是按值传递的。

在向参数传递基本类型值的时候,被传递的值会被赋给一个局部变量,全局的并没有改变。

function add(num){  
     num += 10;  
     return num;   
}  
var count = 20;  
var result = add(count);  
alert(count);//20,没有发生变化  
alert(result);//30 

在向参数传递引用类型值的时候,会把这个值在内存中的地址赋给一个局部变量,因此这个局部变量的变化会反应在函数的外部。

function setname(obj){  
       obj.name = "zhangsan";  
}  
var person = new object();  
setname(person);  
alert(person.name);//zhangsan 
为了证明对象是按值传递的,看下面的例子:
function setname(obj){  
       obj.name = "zhangsan";  
      obj = new object();  
       obj.name = "lisi"; 
}  
var person = new object();  
setname(person);  
alert(person.name);//zhangsan 
这个例子与上一个例子的区别就是setname()函数中添加了两行代码:一行代码为obj重新定义了一个对象,另一行代码为该对象定义了一个带有不同值的name属性。在把person传递给setname()后,其name属性被设置为“zhangsan”,然后,又将一个新对象赋给变量obj,同时将其name属性设置为"lisi",如果person是按引用传递的,那么person就会被自动修改为指向其name属性值为"lisi"的新对象。但是,在接下来访问person.name时,显示的值仍然是“zhangsan”,这说明即使在函数内部修改了参数的值,但原始的引用仍然保持未变。实际上,当在函数内部重写obj时,这个变量引用的就是一个局部对象了,这个局部对象会在函数执行完毕后立即被销毁。

(5)检测类型:检测基本数据类型的时候,用typeof,检测引用数据类型的时候,用instanceof。

alert(person instanceof object);  
alert(colors instanceof array);  
alert(pattern instanceof regexp);  
所有引用类型的值都是object的实例,因此,在检测一个引用类型值和object构造函数时,instanceof操作符始终会返回true。

2.执行环境和作用域

(1)作用域链的用途,是保证对执行环境有权访问的所有变量和函数的有序访问。作用域链的前端,始终都是当前执行代码所在环境的变量对象,一层一层向外直到全局执行环境的变量对象始终都是作用域链的最后一个对象。

内部环境可以通过作用域链访问所有的外部环境,但外部环境不能访问内部环境中的任何变量和函数。

(2)延长作用域链的两种方法:

 

1.try-catch语句的catch块:会创建一个新的变量对象,其中包含的是被抛出的错误对象的声明

2.with语句:会将指定的对象添加到作用域链中

(3)没有块级作用域:

javascript中,if语句中的变量声明会将变量添加到当前的执行环境中。

if(true){  
   var color = "blue";  
}  
alert(color);//"blue"

javascript中,由for语句创建的变量i即使在for循环结束后,也依旧会存在于循环外部的执行环境中。

for(var i=0; i<10; i++){  
    dosomething(i);  
}  
alert(i);//10 

声明变量:使用var声明的变量会自动被添加到最接近的环境中,在函数内部,最接近的环境就是函数的局部环境,在with语句中,最接近的环境是函数环境。如果初始化变量时没有使用var声明,该变量会自动添加到全局环境。

查询标识符:搜索过程从作用域链的前端开始,向上逐级查询,在局部中找到就停止搜索,在局部中没找到,就继续向上搜索,直到全局环境。