书中有这么3句话:
所有函数的参数都是按值传递的。
访问变量有按值和按引用两种方式。
不少开发人员在这一点上可能会感到困惑。
第一次读的时候,懵懵懂懂。既然传递是复制,复制有两种方式,那怎么函数中的传递只有一种方式呢?
我解决问题,尤其是这种特别绕的问题的时候,思路只是一个:细分步骤,越细越好,透彻每一步,加上敏锐的嗅觉,问题实质自然会浮出水面。下面我们就来细分一下这个过程,依旧是书上的实例:
参数是基本类型
function addTen(num){ num += 10; return num; }var count = 20;var result = addTen(count);alert(count); // 20alert(result); // 30
参数是引用类型
function setName(obj){ obj.name = "Nicholas"; }ver person = new Object();setName(person);alert(person.name); // Nicholas
这两个例子中,包含着两个重要的过程。第一个过程发生在函数外部,函数外部变量传递(复制)到函数参数,这一步是按值传递;第二个过程发生在函数内部,在运行函数需要调用参数值的时候,若参数是基本类型,直接读取复制过来的值,而若参数是引用类型,不能直接读取变量的值,而是读取复制来的引用,这时,读取数据就是按引用访问。“函数参数都是按值传递的”说的是第一个过程,第二个过程中引用类型仍会按引用访问对象。
为了更深入的理解,书中又给了一个例子:
function setName(obj){ obj.name = "Nicholas"; obj = new Object(); obj.name = "Greg";}var person = new Object();setName(person);alert(person.name); // Nicholas
这里如果person是按引用传递的话,person就会自动被修改为指向其name属性值为“Greg”的新对象。
而事实上,person是按值传递的。可以将它类比第一个例子,在函数内部改变参数的值,并不会影响外部变量。内部修改参数的值,原始的引用不会改变。