js 变量
转自 http://blog.sina.com.cn/s/blog_68cb8c790100yrxx.html
- 定义变量要用var操作符,后跟变量名,如下:
var color;
像这样未经初始化的变量会被赋值为undefined,因此可以在定义变量的同时设置变量的值,如下: var color = "red";
- 但是要注意var操作符定义的变量将成为定义该变量的作用域中的局部变量,例如这个例子:function doSomething (){
var color = "red";
}
doSomething();
alert(color); 结果就会返回
,color没有被定义,原因是var使得color成为了doSomething这个函数的局部变量,color这个变量在函数退出后就会被销毁。 如果想返回正确结果,把var去掉就可以了。
}
doSomething();
alert(color); 结果就会返回
- 可以用一条语句定义多个变量,只要像下面这样把每个变量(初始化或者不初始化均可)用逗号分开就可以了:
var color = "red",
age = 12,
found = true;
age = 12,
found = true;
- 变量又可分为两种不同的数据类型:基本类型和引用类型。
基本类型:5种Undefined,Null,Boolean,Number和String。这五种基本数据类型的值在内存中分别占固 定大小的空间,可以保存在栈内存中。对于保存基本类型的变量,他们是按值访问的。
引用类型:指那些保存在堆内存中的对象,大概意思是变量中保存的实际上只是一个指针,指向内存中的另外一个位置,该位置保存对象。当查找引用类型的变量时,可以先从栈内存中读取内存地址,然后在找到保存在堆中得值,这种方式叫做按引用访问。(注:下面会提到按值访问和按引用访问的区别。) 如下图:
(所以堆内存比栈内存要大很多)
引用类型:指那些保存在堆内存中的对象,大概意思是变量中保存的实际上只是一个指针,指向内存中的另外一个位置,该位置保存对象。当查找引用类型的变量时,可以先从栈内存中读取内存地址,然后在找到保存在堆中得值,这种方式叫做按引用访问。(注:下面会提到按值访问和按引用访问的区别。) 如下图:
- 保存 基本类型和引用类型的共同点和区别:
共同点:定义它们的方式是类似的:创建一个变量并为该变量赋值。
区别:看下面的例子 var person = new Object();
person.name = "Tony";
alert (person.name); //Tony 你会看到Tony这个结果,这写代码先创建了一个对象,并保存在person中,然后给这个对象添加了一个name属性并赋值为"Tony",然后我们alert访问这个新属性,自然得到了答案。
我们并不能同样的为基本类型添加属性: var name = "Tony";
name.age = 22;
alert (name.age); //undefined 这个例子中我们会看到我们并没有为字符串name添加上age属性。 总结:我们只能给引用类型动态的添加属性,以便未来使用。 (上面绿色这句话错了,经过网友纠正,结果如下:这里面不是没有为字符串name添上age属性,这里存在一个自动封装的问题,字符串是基本类型,而当我们访问或操作字符串的属性、方法时,js会自动将基本类型的字符串封装成对象(类似new String(name)),访问和操作之后再转换为基本类型(类似String的valueOf()),所以name.age = 22这条语句在执行过程中是对封装后的name字符串对象添加属性age,语句执行完之后封装的对象执行域退出,我们将无法再次访问此对象,alert (name.age); //undefined这条语句访问的age为再一次封装之后的字符串的属性,已经不是上次的那个对象了,自然是undefined了)
区别:看下面的例子 var person = new Object();
person.name = "Tony";
alert (person.name); //Tony 你会看到Tony这个结果,这写代码先创建了一个对象,并保存在person中,然后给这个对象添加了一个name属性并赋值为"Tony",然后我们alert访问这个新属性,自然得到了答案。
我们并不能同样的为基本类型添加属性: var name = "Tony";
name.age = 22;
alert (name.age); //undefined 这个例子中我们会看到我们并没有为字符串name添加上age属性。 总结:我们只能给引用类型动态的添加属性,以便未来使用。 (上面绿色这句话错了,经过网友纠正,结果如下:这里面不是没有为字符串name添上age属性,这里存在一个自动封装的问题,字符串是基本类型,而当我们访问或操作字符串的属性、方法时,js会自动将基本类型的字符串封装成对象(类似new String(name)),访问和操作之后再转换为基本类型(类似String的valueOf()),所以name.age = 22这条语句在执行过程中是对封装后的name字符串对象添加属性age,语句执行完之后封装的对象执行域退出,我们将无法再次访问此对象,alert (name.age); //undefined这条语句访问的age为再一次封装之后的字符串的属性,已经不是上次的那个对象了,自然是undefined了)
- 复制 变量的值
基本类型的复制:会在栈中创建一个新值,然后把该值复制到新变量分配的位置上。 var num1 = 5;
var num2 = num1; 储存过程如下图
如图,num1中的5和num2中的5是完全独立的!这两个变量可以参与任何操作而不受任何影响。
引用类型的复制:同样会将储存在栈内存中的值复制一份,不同的是这个值的副本实际上是一个指针,他指向储存在堆中的一个对象。这两个对象实际上引用同一个对象。因此改变其中一个的值,就会影响另外一个。如下例: var obj1 = new Object(); var obj2 = obj1; obj1.name = "Tony"; alert(obj2.name); //Tony 存储过程如下图:
如图所示,这两个变量引用的都是同一个对象。
var num2 = num1; 储存过程如下图
引用类型的复制:同样会将储存在栈内存中的值复制一份,不同的是这个值的副本实际上是一个指针,他指向储存在堆中的一个对象。这两个对象实际上引用同一个对象。因此改变其中一个的值,就会影响另外一个。如下例: var obj1 = new Object(); var obj2 = obj1; obj1.name = "Tony"; alert(obj2.name); //Tony 存储过程如下图:
- 传递参数:(参数只能按值传递)
1.向参数传递基本类型 function addTen (num){
num +=10;
return num;
}
var count =20;
var result = addTen(count);
alert(count);
alert(result); 这里的函数addTen有一个参数num,这个参数num实际上是函数的局部变量,在调用这个函数时,count作为参数被传给函数,这个变量的值是20,于是20就被复制给num,以便在函数addTen中使用。在函数内部,num的值被加上了10,就像上文中提到,它并不影响外面count变量的值,num和count仅仅是有相同的值。
2.向参数传递引用类型 function setName(obj){
obj.name = "Tony";
}
var person =new Object();
setName(person);
alert(person.name); 以上代码创建了一个对象,并保存在person中,然后这个对象被传送到setName函数中之后被复制给了obj,在这个函数内部,obj和person引用的是同一个对象,于是内部的obj添加了name属性后,外部的person也会有所反应,同样的被添加了name属性。 到此为止,肯定很多人认为向参数传递引用类型是按引用访问的,其实并不是,看下面的代码: function setName(obj){
obj.name = "Tony"; obj = new Object();
obj.name = "Tom";
}
var person =new Object();
setName(person);
alert(person.name); 代码中添加了红色的两行,如果是按引用传递的话,结果会显示Tom,可是结果却是Tony,这就很好的说明向参数传递引用类型的时候仍然是按值传递的。
num +=10;
return num;
}
var count =20;
var result = addTen(count);
alert(count);
alert(result); 这里的函数addTen有一个参数num,这个参数num实际上是函数的局部变量,在调用这个函数时,count作为参数被传给函数,这个变量的值是20,于是20就被复制给num,以便在函数addTen中使用。在函数内部,num的值被加上了10,就像上文中提到,它并不影响外面count变量的值,num和count仅仅是有相同的值。
2.向参数传递引用类型 function setName(obj){
obj.name = "Tony";
}
var person =new Object();
setName(person);
alert(person.name); 以上代码创建了一个对象,并保存在person中,然后这个对象被传送到setName函数中之后被复制给了obj,在这个函数内部,obj和person引用的是同一个对象,于是内部的obj添加了name属性后,外部的person也会有所反应,同样的被添加了name属性。 到此为止,肯定很多人认为向参数传递引用类型是按引用访问的,其实并不是,看下面的代码: function setName(obj){
obj.name = "Tony"; obj = new Object();
obj.name = "Tom";
}
var person =new Object();
setName(person);
alert(person.name); 代码中添加了红色的两行,如果是按引用传递的话,结果会显示Tom,可是结果却是Tony,这就很好的说明向参数传递引用类型的时候仍然是按值传递的。
- 检测变量类型
1.检测基本类型:用typeof操作符 例: var s = "Tony";
var b = true;
var i = 22;
var u =
var n = null;
var o = new Object;
alert (typeof s); //string
alert (typeof b); //boolean
alert (typeof i); //number
alert (typeof u); //undefined
alert (typeof n); //object
alert (typeof o); //object typeof操作符可以很好的检测出基本类型。但检测引用类型时并不好用,我们不想知道他是不是对象,而是想知道他是什么类型的对象。
2.引用类型的检测:用instanceof操作符 例: alert(person instanceof Object); //变量person是Object吗? alert(color instanceof Array); alert(color instanceof RegExp);
var b = true;
var i = 22;
var u =
var n = null;
var o = new Object;
alert (typeof s); //string
alert (typeof b); //boolean
alert (typeof i); //number
alert (typeof u); //undefined
alert (typeof n); //object
alert (typeof o); //object typeof操作符可以很好的检测出基本类型。但检测引用类型时并不好用,我们不想知道他是不是对象,而是想知道他是什么类型的对象。
2.引用类型的检测:用instanceof操作符 例: alert(person instanceof Object); //变量person是Object吗? alert(color instanceof Array); alert(color instanceof RegExp);

浙公网安备 33010602011771号