按值传递和引用传递

欢迎你们关注个人 githubgit

概述

最近在看到函数按值传递仍是引用传递的时候产生了困惑,忽然想到这个问题好像从第一次看红宝书就一直有这个困惑,因而各类搜,可是网上的种种回答也很不相同,想了两天终于算是有个理由能够说服本身了。咱们先不讨论按值传递和引用传递的名字的定义,不少时候都是被名字的定义误导了。github

实质重于形式,名字能够有不少,咱们就不讨论到底该叫什么。只想说在现代的语言中参数的传递方式只有按值传递了,好比JS,没有引用传递。我当时比较困惑是将引用类型的复制当成了引用传递,准确的讲这应该叫引用访问,好像这是文字游戏的感受。下面来简单的说一下。函数

基本概念

JS的值分为基本类型和引用类型spa

  • 基本类型:存储在栈中,由于占据的空间固定,存储在栈中更容易查找变量的值设计

  • 引用类型:存储在堆中,由于引用值大小会改变,因此不能放在栈中,否则会下降查询效率。可是能够将该引用值的地址存储在栈中,地址的大小是固定的。code

当咱们访问一个对象的时候,首先获得的是从栈中找到的该对象在堆内存中的地址,而后按照地址去获取对象中的值。cdn

当咱们复制基本类型变量和引用类型变量的时候对象

  • 基本类型复制:在栈中新开一个字段,将值复制到新字段,新值和旧值是两个独立的字段,互不影响blog

  • 引用类型复制:在栈中新开一个字段,将对象在堆内存中的地址(引用)复制到新字段,新值和旧值指向堆内存中的同一个对象,当咱们要操做变量的时候,操做的是变量的引用。当给对象添加属性的时候,操做的是堆内存中实际的对象游戏

基本类型的复制:

引用类型的复制:

传递参数

当咱们传递引用类型的参数时,就是引用类型的复制,函数的形参仍是和实参指向了同一个引用类型,此时操做变量是操做的变量的引用,当给对象添加属性的时候,操做的是堆内存中实际的对象。咱们能够认为是按地址传递

当咱们操做变量的时候,实际是:

因此咱们就能够理解下面的这些代码了:

function setName(obj) {
    obj.name = 'zhangsan'   // 操做的是堆内存中的对象
}

var person = new Object()
setName(person)
console.log(person.name)  // zhangsan
复制代码

function setName(obj) {
    obj.name = 'zhangsan'
    obj = new Object()      // 操做的是对象的引用
    obj.name = 'lisi'
}

var person = new Object()
setName(person)
console.log(person.name) // zhangsan
复制代码

因此说函数是按值传递参数,JS没有引用传递



参考资料:

《JS高级程序设计》

https://www.zhihu.com/question/27114726

https://www.zhihu.com/question/51018162

相关文章
相关标签/搜索