今天看到高程关于传递参数这一张的时候,说到,参数不管是基本类型还是引用类型的传递都是按值传递,但是
demo:
function setName(obj){
obj.name=“Nicholas”;
obj=new Object();
obj.name=“Greg”;
}
var person=new Object();
setName(person);
alert(person.name) //“Nicholas”
书上说当函数内部重写obj时,这个变量引用的就是一个局部对象了,而这个局部对象会在函数执行完毕后立即被销毁(还是理解不了)
如果把obj=new Object();删掉,返回值为Greg;
于是重新看了内存的分配以及按值传递与按引用传递的区别,终于有了一点眉目
基本类型:存储在栈(stack)中的简单数据段,也就是说,它们的值直接存储在变量访问的位置。
引用类型:存储在堆(heap)中的对象,也就是说,存储在变量处的值是一个指针(point),指向存储对象的内存地址。
在ECMAScript中是不允许直接访问保存在堆内存中的对象的,所以在访问一个对象时,首先得到的是这个对象在堆内存中的地址,然后再按照这个地址去获得这个对象中的值,这就是按引用访问。而原始类型的值则是可以直接访问到的。
对于引用类型传参时的复制变量情况
在将一个保存着对象内存地址的变量复制给另一个变量时,会把这个内存地址赋值给新变量(因为这个引用值只能按引用访问得到),也就是说这两个变量都指向了堆内存中的同一个对象,他们中任何一个作出的改变都会反映在另一个身上。
进行传传参时:
基本类型只是把变量的值复制了一份给参数,之后参数和变量就互不影响了
而引用类型:对象变量里面的值是这个对象在堆内存中的内存地址,因此它传递的值也就是这个内存地址,这也就是为什么函数内部对这个参数的修改会体现在外部的原因了,因为它们都指向同一个对象。
用代码解释可能理解更形象:
注:代码范例来自JS高程P71。
function setName(obj) {
obj.name="Nicholas";
obj=new Object( );
obj.name="Greg";
}
var person=new Object( );
setName(person);
//根据上述函数参数的特点,可以利用arguments对象来重写这个函数:
function setName( ) {
arguments[0].name="Nicholas";
arguments[0]=new Object( );
arguments[0].name="Greg";
}
//将参数person传入setName函数,函数执行步骤入下:
function setName(person){
arguments[0]=person; //将arguments[0]和person指向同一个对象
arguments[0].name="Nicholas"; //也即person.name="Nicholas"
arguments[0]=new Object; //重新定义arguments[0]。这时,arguments[0]已经跟 person“脱钩”
arguments[0].name="Greg"; //这行代码跟person已经没有关系了
}
//结果自然很明朗,没悬念
alert(person.name); // "Nicholas";
五、总结
- 在ECMAScript中,所谓参数按值传递就是,将形式参数初始化为实际参数的值。或者说将所传递的实际参数的值复制到函数内部的arguments数组中。对于基本类型值,就是在函数内部创建了一个该值的副本;对于引用类型值则复制了一个指向某个对象的指针。所传递的参数依次对应于arguments数组中的arguments[0],arguments[1]等元素。
- 而按引用传递,则相当于将形式参数初始化为实际参数本身。
注意:一个是只传递变量的值,一个是传递整个变量。这两者的内涵是完全不同的。
我们知道,ECMAScript中,每个变量都是一个用于保存值的占位符。如果参数是对像,则参数按值传递,意味着在函数内部,只能操作实际参数(对像)的属性和值,而不能操作实际参数(对像)本身。也就是说,你可以通过函数来改变函数外部所传入对像(参数)的属性和属性值;但你不能删除该变量,或改变此变量的引用对象。
对比两个例子巩固
var obj={
attr:'obj attr value'
};
function func(o){
o.attr="new attr value!";
}
func(obj);
console.log(obj.attr); //new arr value
var obj={
attr:'obj attr value'
};
function func(obj){
obj={attr:'new attr value!'}; 等价于obj=new Object( );
obj.arr=“new attr value”;
}
func(obj);
console.log(obj.attr); //obj attr value'
参考:http://www.jianshu.com/p/26ab38bdc176