您的位置:首页 > Web前端 > JavaScript

JavaScript:变量

2016-01-26 14:51 344 查看
基于JavaScript变量松散类型的本质,变量只是在特定时间用于保存特定值的一个名字。由于不存在定义某个变量必须要保存何种数据类型值的规则,变量的值及数据类型可以在脚本的生命周期内改变。

基本类型和引用类型的值

  JavaScript变量可能包含两种不同数据类型的值:基本类型值和引用类型值。基本类型值指的是简单的数据段,而引用类型值指那些可能有多个值构成的对象。

  在将一个值赋给变量时,解析器必须确定这个值是基本类型值还是引用类型值。基本数据类型:undefined、null、Boolean、number和string。这5种基本数据类型是按值访问的,因此可以操作保存在变量中的实际值。

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

1.动态的属性

  定义基本类型值和引用类型值的方式是类似的:创建一个变量并为该变量赋值。但是,当这个值保存到变量中以后,对不同类型值可以执行的操作时不同的。对于引用类型的值,可以为其添加属性和方法,也可以删除属性和方法。例如:

var person = new Object();
person.name = "张三";
alert(person.name); // 张三


以上创建了一个对象并保存在变量person中,然后为对象添加了name属性,并将字符串值“张三”赋给了这个属性。紧接着,又通过alert()函数访问了这个新属性。

  但是,不能给基本类型的值添加属性。

var name = "张三";
name.age = "20";
alert(name.age);    // undefined


2.复制变量

  从一个变量赋值向另一个变量赋值基本类型值和引用类型值时,基本类型和引用类型也存在不同。从一个变量向另一个变量复制基本类型的值,会在变量对象上创建一个新值,然后把该值赋值到为新变量分配的位置上。

var num1 = 2;
var num2 = num1;


num1中保存的值是2。当使用num1的值初始化num2时,num2中的值也为2。但是num1和num2中的值是独立的。该值只是num1中2的一个副本。这两个变量可以参加任意操作而不会相互影响

  当从一个变量向另一个变量赋值引用类型的值时,同样也会将存储的变量对象的值赋值到新变量中。不同的是,这个副本实际上是一个指针,而这个指针指向存储在堆中的一个对象。赋值操作后,两个变量实际上将引用同一个对象。因此,改变其中一个变量,就会影响另一个变量。

var obj1 = new Object();
var obj2 = obj1;
obj1.name = "张三";
alert(obj2.name);   // “张三”


3.传递参数

  JavaScript中的所有函数的参数都是按值传递的。把函数外部的值复制给函数内部的参数,就和把值从一个变量赋值到另一个变量一样。基本数据类型值的传递如同基本类型变量的复制一样,而引用类型值的传递,则如同引用类型变量的复制一样。

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

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


函数addTen()有一个参数num,实际是函数的局部变量。在调用这个函数时,变量count作为参数被传递给函数,这个变量的值是20。于是,数值20被赋值给参数num。在函数内部,参数num的值加上了10,但是这一变化不会影响函数外部的count变量。参数num和count是相互独立的,仅仅是具有相同的值。如果num是按引用传递,那么变量count的值也会变成30。

function setName(obj) {
obj.name = "萧萧弈寒";
}
var person = new Object();
setName(person);
alert(person.name); // “萧萧弈寒”


上面创建了一个对象,并将其保存在变量person中。然后,这个变量被传递到setName()函数之中就被复制给了obj。在这个函数内部,obj和person引用的是同一个对象。于是当在函数内部为obj添加属性name时,函数外部的person对象会有所反应,因为person指向的对象在堆内存中只有一个,而且是全局对象。

  为了证明对象是按值传递的,再看一个例子:

function setName(obj) {
obj.name = "萧萧弈寒";
obj = new Object();
obj.name = "李四";
}

var person = new Object();
setName(person);
alert(person.name); // "萧萧弈寒"


在把person传递给setName()后,其属性name被设置为“萧萧弈寒”。然后,又将一个新对象赋给变量obj,同时将其name属性设置为“李四”。如果person是按引用传递的,那么person就会被自动修改为name属性值为“李四”的对象。但是,访问person.name时,显示的值仍然是“萧萧弈寒”。这说明即使在函数内部修改了参数的值,但原始的引用仍然保持不变。实际上,当函数内重写obj时,这个变量引用的是一个局部对象。函数执行完对象就会被销毁。

3.类型检测

  在检测基本数据类型时使用typeof,但是检测引用类型值时,我们需要知道某个值是什么类型的对象。对此,JavaScript提供了instanceof操作符。语法规则为:

result = variable instanceof constructor


如果变量是给定引用类型的实例,那么instanceof操作符就会返回true。例如:

var p = new Object();
var i = 10;
var c = ['red', 'blue'];

alert(p instanceof Object);     // true
alert(i instanceof Object);     // false
alert(c instanceof Array);      // true
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: