js函数参数是按值传递的,不是按引用传递

今天看到高程关于传递参数这一张的时候,说到,参数不管是基本类型还是引用类型的传递都是按值传递,但是

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' 

猜你喜欢

转载自blog.csdn.net/hefeng6500/article/details/82710126