加入收藏 | 设为首页 | 会员中心 | 我要投稿 甘孜站长网 (https://www.0836zz.com.cn/)- 运维、物联设备、数据计算、智能推荐、云管理!
当前位置: 首页 > 运营中心 > 建站资源 > 优化 > 正文

JavaScript是如何工作的:JavaScript的共享传递和按值传递

发布时间:2019-04-20 01:59:07 所属栏目:优化 来源:前端小智
导读:关于JavaScript如何将值传递给函数,在互联网上有很多误解和争论。大致认为,参数为原始数据类时使用按值传递,参数为数组、对象和函数等数据类型使用引用传递。 按值传递 和 引用传递参数 主要区别简单可以说: 按值传递:在函数里面改变传递的值不会影响
副标题[/!--empirenews.page--]

关于JavaScript如何将值传递给函数,在互联网上有很多误解和争论。大致认为,参数为原始数据类时使用按值传递,参数为数组、对象和函数等数据类型使用引用传递。

按值传递 和 引用传递参数 主要区别简单可以说:

  • 按值传递:在函数里面改变传递的值不会影响到外面
  • 引用传递:在函数里面改变传递的值会影响到外面

但答案是 JavaScript 对所有数据类型都使用按值传递。它对数组和对象使用按值传递,但这是在的共享传参或拷贝的引用中使用的按值传参。这些说有些抽象,先来几个例子,接着,我们将研究JavaScript在 函数执行期间的内存模型,以了解实际发生了什么。

按值传参

在 JavaScript 中,原始类型的数据是按值传参;对象类型是跟Java一样,拷贝了原来对象的一份引用,对这个引用进行操作。但在 JS 中,string 就是一种原始类型数据而不是对象类。

  1. let setNewInt = function (i) {  
  2. ii = i + 33;  
  3. };  
  4. let setNewString = function (str) {  
  5. str += "cool!";  
  6. };  
  7. let setNewArray = function (arr1) {  
  8. var b = [1, 2];  
  9. arr1 = b;  
  10. };  
  11. let setNewArrayElement = function (arr2) {  
  12. arr2[0] = 105;  
  13. };  
  14. let i = -33;  
  15. let str = "I am ";  
  16. let arr1 = [-4, -3];  
  17. let arr2 = [-19, 84];  
  18. console.log('i is: ' + i + ', str is: ' + str + ', arr1 is: ' + arr1 + ', arr2 is: ' + arr2);  
  19. setNewInt(i);  
  20. setNewString(str);  
  21. setNewArray(arr1);  
  22. setNewArrayElement(arr2);  
  23. console.log('现在, i is: ' + i + ', str is: ' + str + ', arr1 is: ' + arr1 + ', arr2 is: ' + arr2);  

运行结果

  1. i is: -33, str is: I am , arr1 is: -4,-3, arr2 is: -19,84 
  2.  
  3. 现在, i is: -33, str is: I am , arr1 is: -4,-3, arr2 is: 105,84  

这边需要注意的两个地方:

1)第一个是通过 setNewString 方法把字符串 str 传递进去,如果学过面向对象的语言如C#,Java 等,会认为调用这个方法后 str 的值为改变,引用这在面向对象语言中是 string 类型的是个对象,按引用传参,所以在这个方法里面更改 str 外面也会跟着改变。

但是 JavaScript 中就像前面所说,在JS 中,string 就是一种原始类型数据而不是对象类,所以是按值传递,所以在 setNewString 中更改 str 的值不会影响到外面。

2)第二个是通过 setNewArray 方法把数组 arr1 传递进去,因为数组是对象类型,所以是引用传递,在这个方法里面我们更改 arr1 的指向,所以如果是这面向对象语言中,我们认为最后的结果arr1 的值是重新指向的那个,即 [1, 2],但最后打印结果可以看出 arr1 的值还是原先的值,这是为什么呢?

共享传递

Stack Overflow上Community Wiki 对上述的回答是:对于传递到函数参数的对象类型,如果直接改变了拷贝的引用的指向地址,那是不会影响到原来的那个对象;如果是通过拷贝的引用,去进行内部的值的操作,那么就会改变到原来的对象的。

可以参考博文 JavaScript Fundamentals (2) – Is JS call-by-value or call-by-reference?

  1. function changeStuff(state1, state2)  
  2. {  
  3. state1.item = 'changed';  
  4. state2 = {item: "changed"};  
  5. }  
  6. var obj1 = {item: "unchanged"};  
  7. var obj2 = {item: "unchanged"};  
  8. changeStuff(obj1, obj2);  
  9. console.log(obj1.item); // obj1.item 会被改变  
  10. console.log(obj2.item); // obj2.item 不会被改变  

缘由: 上述的 state1 相当于 obj1, 然后 obj1.item = 'changed',对象 obj1 内部的 item 属性进行了改变,自然就影响到原对象 obj1 。类似的,state2 也是就 obj2,在方法里 state2 指向了一个新的对象,也就是改变原有引用地址,这是不会影响到外面的对象(obj2),这种现象更专业的叫法:call-by-sharing,这边为了方便,暂且叫做 共享传递。

内存模型

(编辑:甘孜站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读