欢迎你们关注个人 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高级程序设计》
https://www.zhihu.com/question/27114726
https://www.zhihu.com/question/51018162