js中的函数传参:值传递,引用传递 or 共享传递

周末的时候在看common.js规范时候遇到一个问题:

function require () {
    let Modules = {exports:{}};
    (function (Modules, exports) {
        let someFn = function () {};
        ***//exports和modules.exports断开了引用***
        exports = someFn;
        Modules.exports = someFn;
    })(Modules, Modules.exports);
    return Modules.exports;
}

看注释的部分,我看了很多博客都这样说,但是为什么,却寥寥无几。我就仔细研究一下,
先将代码的立即执行函数拿出来:

function XXX(Modules, exports) {
     let someFn = function () {};
     ***//exports和modules.exports断开了引用***
     exports = someFn;
     Modules.exports = someFn;
 }
 XXX(Modules, Modules.exports)

就是一个普通的函数和执行,那么问题就出现在传参这块。后来看了一下js的传参,才发现js的传参不是call by reference(按引用)而是 call by sharing(按共享传递),具体看维基百科Evaluation strategy。但是很难理解,这里我就发表一下个人的见解:

function someFun (num, obj1, obj2) {
    num *= 20;
    obj1.name = "李四";
    obj2 = 123;
}

let num = 10;
let person1 = {name: "张三"};
let person2 = {age: 24};

someFun(num, person1, person2);

按值传递:
形参会把实参的内存拷贝一下,这时形参和实参是两块内存,所以修改形参的内存,不会影响到实参的内存。所以形参的改变不会影响到实参。例如上面的num变量,可以看做将num的内存复制给形参num,这时候值为10的内存有两块,函数内部操作的是形参的内存,与函数外的内存无关。
按引用传递:
首先实参本身就是一个保存内存地址的变量(注意并不是直接的内存而是内存所在的地址),然后形参将这个指向内存的地址拷贝下来给形参,此时内存只有一块,只是有两个引用指向它。所以当你修改它的内存时候其实影响到了两个引用。
例如上面代码中的obj1修改name属性时,因为person1和obj1的name的属性保存的都是一块内容为”张三”的内存,所以当我们修改它的时候,person1和obj1都会被影响到。
按共享传递
它与引用传递的不同是,引用并没有内存,例如c语言中的指针,只是一个指向;但是共享传递不是,它会将实参的所在的地址也拷贝进来,这个变量本身就可以看做一个内存,只是这个内存的一个值保存另一块内存的地址。所以我们可以运行上面的函数发现,obj2的值变了,但是person2没有任何影响,因为此时它们是两块不同的内存,而person1和obj1之所以可以变,是因为person1和obj1两块内存中的一个name所在的区域保存了指向一块内容为”张三”的内存的引用(内存地址),并且这块内存是惟一的,所以obj1表现的像是引用传递。

你可能感兴趣的:(程序员笔记,web开发笔记)