JS传值OR传引用

简介: js中传值到底是什么方式,值传递还是引用传递.nodejs 为什么会有exports和module

outline:

1. call by value(值传递)

2. call by reference(引用传递)

3. call by sharing(共享传递)

这里我们以C语言为例,比较call by value和call by reference

#include <stdio.h>
int test(int a1,int *b1){
    a1 = 3;
    *b1 = 4;
}
int main(){
    int a = 1;
    int b = 2;
    printf("a = %d, b = %d\n",a, b);//a=1,b=2;
    test(a, &b);
    printf("a = %d, b = %d\n",a, b);//a=1,b=4;
    return 0;
}

在上面这段C代码中,
a => a1,按照值传递(call by value)的方式,修改a1并不影响a
b => b1,按照引用传递(call by reference)的方式,修改b1影响b

那么JS中到底是按照什么方式传值呢?
先看一段代码

var a = 1;
var o1 = {
    name : 'jiang1',
    age : 22
};
var o2 = {
    name : 'jiang2',
    age : 23
};
function foo(a,o1,o2){
    a = 2;
    o1.age = 23;
    o2 = {
        name: 'jiang3',
        age:24
    };
}
console.log(a);//1
console.log(o1);//{name: "jiang1", age: 22}
console.log(o2);//{name: "jiang2", age: 23}
foo(a,o1,o2);
console.log(a);//1
console.log(o1);//{name: "jiang1", age: 23}
console.log(o2);//{name: "jiang2", age: 23}

这里我们把a,o1,o2的foo函数执行前后变化情况列出来,如表所示:

变量 是否是对象 foo执行前 foo执行后
a 1 1
o1 {name: "jiang1", age: 22} {name: "jiang1", age: 23}
o2 {name: "jiang2", age: 23} {name: "jiang2", age: 23}
从表中,我们可以初步看出几条rules: 1. 对于非对象的变量,传递的方式跟值传递是一样的效果,foo中的a并不会影响外面的a的值 2. 对于对象类型的变量,传递的方式有点像值传递(比如o2),但是又有点像引用传递(比如o1),我们可以分为两中情况: 对于形如o1的,函数接受对象o1,在函数内修改o1的属性,这个时候外面o1会受到影响. 对于形如o2的,函数接受对象o2,在函数内修改o2的指向,令o2指向一个新的对象,这种情况外面的o2不受影响. 这种兼具 call by valuecall by reference的传递方式,我们就称为 call by sharing. 对于这种特殊的传递方式,我们可以 stackoverflow总结的去理解.没想到跟我们列表总结的3条rules是一样. 下面我们在来看一个实际的例子 关于nodejs为什么要有exports和module 这个例子我们只有两个js,分别是test.js和x.js
//test.js
var x = require('./x.js');
console.dir(x)

首先我们通过一个简单的log看下exports和module的关系:

//x.js
console.log(exports===module.exports)
console.dir(module);

得到如下结果
exports_module.png
我们可以肯定

  1. exports就是module.exports
  2. 外面的test.js中require得到的是exports.

那么为啥那么这里又要exports又要module.exports呢,感觉多次一举.这里结合我们上面所说的call by sharing,我想大家应该能想到点什么.考虑两个场景,

  1. 我们要修改exports的属性又要是外面的exports生效(即require可以看到我们给exports绑定的属性)
  2. 我们要修改exports同时又要外面的exports生效(即require可以看到我们给exports赋予的新的值)
    对于第一种情况,大家的代码通常都能实现,比如
//x.js
var test = function(){
    console.log("test");
}
exports.test = test;

这个时候我们结合call by sharing想一想,是不是我们改变了exports的属性就可以改变外面的exports.
那么对于第二种情况,我们有该怎么办呢?也许有的说我可以直接复制

//x.js
var test = function(){
    console.log("test");
}
exports = test;

很可惜,并没什么卵用.这种用法和我们上面的o2不是一样的情况么?其实估计聪明的读者有的可能已经想到了,exports是moudle的属性,既然我改exports没有用,那么我来改module.exports不久可以了么.bingo!就是这样的

//x.js
var test = function(){
    console.log("test");
}
module.exports = test;

到这里,我想读者们应该明白了为什么要有exports和module了吧.
对于js里的传值,我想总结为默认情况下就按照值传递去理解,如果想要实现引用传递,那么就去找这个对象、属性所属的对象就好啦.

目录
相关文章
|
4月前
|
JavaScript 索引
用原生js的postMessage实现iframe传值,也可以用于跨域嵌套iframe传值
用原生js的postMessage实现iframe传值,也可以用于跨域嵌套iframe传值
用原生js的postMessage实现iframe传值,也可以用于跨域嵌套iframe传值
|
1月前
|
JavaScript 前端开发 Java
JavaScript中的传值与传引用
JavaScript中的传值与传引用
14 0
|
4月前
|
JavaScript 前端开发
js中父子元素如何传值
js中父子元素如何传值
34 0
|
9月前
|
移动开发 小程序 JavaScript
微信小程序学习实录7(H5嵌入小程序、获取微信收货地址、数组对象url传值、js获取url参数)
微信小程序学习实录7(H5嵌入小程序、获取微信收货地址、数组对象url传值、js获取url参数)
223 0
|
9月前
|
JavaScript Java
JS实现页面跳转并传值
JS实现页面跳转并传值
|
JavaScript
[JS ES6]传值和传址
[JS ES6]传值和传址
47 0
[JS ES6]传值和传址
|
Web App开发 JavaScript 前端开发
Android中WebView加载本地Html,与JavaScript与Android方法相互传值(续)
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010046908/article/details/51809558 ...
959 0
|
Web App开发 JavaScript 前端开发
Android中WebView加载本地Html,与JavaScript与Android方法相互传值
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010046908/article/details/51759125 最近在做项目中,要使用HightChart来实现心电图,于是,使用WebView加载本地html页面,但是数据是通过蓝牙设备采集的数据,用Java代码获取的数据,需要将数据传到JavaScript中去,使用来绘制心电图。
1505 0