ECMAScript 变量可能包含两种不同数据类型的值:基本类型值和引用类型值。 基本类型值指的是简单的数据段,而引用类型值指那些可能由多个值构成的对象。
5 种基本数据类型: Undefined、 Null、 Boolean、 Number 和 String。
这 5 种基本数据类型是按值访问的,因为可以操作保存在变量中的实际的值。
引用类型的值是保存在内存中的对象。与其他语言不同,
JavaScript 不允许直接访问内存中的位置,也就是说不能直接操作对象的内存空间。在操作对象时,实际上是在操作对象的引用而不是实际的对象。为此,引用类型的值是按引用访问的。
动态的属性
对于引用类型的值,我们可以为其添加属性和方法,也可以改变和删除其属性和方法。
对象不被销毁,设置的属性和方法,将一直存在。
不能给基本类型的值设置属性和方法。
复制变量值
如果从一个变量向另一个变量复制基本类型的值,会在变量对象上创建一个新值,然后把该值复制
到为新变量分配的位置上。
这两个变量可以参与任
何操作而不会相互影响。(复制变量的值)
当从一个变量向另一个变量复制引用类型的值时,同样也会将存储在变量对象中的值复制一份放到
为新变量分配的空间中。不同的是,这个值的副本实际上是一个指针,而这个指针指向存储在堆中的一
个对象。复制操作结束后,两个变量实际上将引用同一个对象。因此,改变其中一个变量,就会影响另
一个变量。(复制的是引用指针)
传递参数
ECMAScript 中所有函数的参数都是按值传递的。也就是说,把函数外部的值复制给函数内部的参
数,就和把值从一个变量复制到另一个变量一样。
访问变量有按值和按引用两种方式,而参数只能按值传递。
在向参数传递基本类型的值时,被传递的值会被复制给一个局部变量(即命名参数,或者用ECMAScript 的概念来说,就是 arguments 对象中的一个元素)。
1
2
3
4
5
6
7
8
|
function
addTen(num){
num +=10;
return
num;
}
var
count = 20;
var
result = addTen(count);
alert(count);
//20
alert(result);
//30
|
在向参数传递引用类型的值时,会把这个值在内存中的地址复制给一个局部变量,因此这个局部变量的变化会反映在函数的外部。传给函数的是数值的一个引用,函数中对其属性的修改外部可见,但用新引用覆盖其则在外部不可见。
1
2
3
4
5
6
|
function
setName(obj){
obj.name =
"staven"
;
}
var
person =
new
Object();
setName(person);
alert(person.name); //staven
|
普通赋值
1
2
3
4
|
var
a = 1;
var
b = a;
//赋的是a的复制值
b ++;
alert(a);
//"1" b的修改不影响a
|
1
2
3
4
|
var
a = [1];
var
b = a;
//赋的是a的引用
b[0] ++;
alert(a);
//"2" b的修改对a也有效
|
参数传值传递:传给函数的是数值的一个复制,函数中对其的修改外部不可见
1
2
3
4
5
6
7
8
9
10
11
12
|
var
a = 1;
var
b = 2;
function
change(a,b) {
var
c = a;
a = b;
//用新引用覆盖
b = c;
alert(a);
//"2"
alert(b);
//"1"
}
change(a,b);
alert(a);
//"1"
alert(b);
//"2"
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
var
a = [1, 2, 3];
var
b = [5, 6];
function
change(a,b) {
a[0] = 4;
//对其属性的修改外部可见
var
c = a;
a = b;
//用新引用覆盖
b = c;
alert(a);
//"5,6"
alert(b);
//"4,2,3"
}
change(a,b);
alert(a);
//"4,2,3"
alert(b);
//"5,6"
|
1
2
3
4
5
6
7
8
9
10
11
|
var
a = [1, 2, 3];
var
b = [5, 6];
function
change() {
var
c = a;
a[0] = 4;
a = b;
b = c;
};
change();
alert(a);
//"5,6"
alert(b);
//"4,2,3"
|
传值的比较比较的是数值 而传址的比较比较的是引用。
参数传递角度理解闭包
1
2
3
4
5
6
7
8
|
var
add_handlers =
function
(nodes) {
var
i;
for
(i = 0, l = nodes.length; i < l; i ++) {
nodes[i].onclick =
function
(e) {
alert(i);
// 当然这里的结果必然是每次alert的都是节点总数。。。。
}
}
};
|
此时i是父级函数作用域的变量的引用。给每个节点设置onclick事件的时候将i的引用传递给了alert,当我点击节点触发onclick事件的时候,i的值已经变成了节点总数。
1
2
3
4
5
6
7
8
9
10
11
|
var
add_handlers =
function
(nodes) {
var
i;
for
(i = 0, l = nodes.length; i < l; i ++) {
nodes[i].onclick =
function
(i) {
return function (){
alert(i);
}
}(i);
}
};
|
这样修改后之所以正确是因为此时传进去的是i的值的复制。
检测类型
typeof 操作符是确定一个变量是字符串、数值、布尔值,还是 undefined 的最佳工具。如果变
量的值是一个对象或 null,则 typeof 操作符都会返回"object"。
如果变量是给定引用类型的实例,那么
instanceof 操作符就会返回 true。
1
2
3
4
5
6
7
8
|
function
setName(obj){
obj.name =
"staven"
;
obj =
new
Object();
obj.name =
"Bob"
;
}
var
person =
new
Object();
setName(person);
alert(person.name);
//staven
|