传递只有一种 —— 按值传递

值传递应该是JS最基本的一个知识点了,网上也有不少说法,有按值传递,有按引用传递,还有按共享传递。what?javascript

先说结论

我一直认为,学习应该去刨根问底。抓住他的核心点,找到事物的本质。因此在这里重新给你们梳理下。java

下面我先说下个人结论:学习

传递只有一种,就是 按值传递 按值传递 按值传递,重要的事情要讲三遍哦。ui

数据类型

标准规定,JavaScript 有 6种 基本类型,string number boolean null undefined symbolObject类型spa

咱们首先来看下,这七种类型在内存中是怎么分配的。3d

堆栈结构

内存是分为栈区和堆区的code

当咱们声明6种基本类型的时候,就是在栈区开辟一段空间。cdn

当咱们声明一个Object类型的时候,在堆区和栈区各分配一段空间,堆区是Object声明的实体,栈区存放的是指向堆区的地址。对象

知识延伸

标准里面规定了,全部基本类型的值都是不可改变的。blog

var a = 1;

a = 2;
复制代码

你可能说不对吧,上面的代码,a就从1变成2了。

对,上面的变量a,确实变了。要理解上面那句话,咱们就须要明白 基本类型值自己 和 一个被赋值基本类型的变量的区别。值不可更改,变量能够从新赋值。

下面咱们看一下,当咱们赋值的时候,内存中是怎么工做的。

当咱们声明 a 而且赋值为 1 的时候,栈区分配一段空间,值为1

当咱们赋值为2的时候,并不会修改 1 所在空间,而是重新分配一段空间,值为 2,而且把这个赋值给变量 a

值传递

上面的东西咱们都明白了,如今咱们再来看看按值传递是怎么回事。

第一种情形

var a = 1;
function getNum(p){
    p = 10;
    return p;
}
getNum(a) // 10
a  // 1
复制代码

执行方法的时候,会把 a 的值,复制一份传递给形参 p

因为 a 的值是 1 ,因此 p 的值也是 1

第二种情形

var a = {
    x: 1
}
function getNum(p){
    p.x = 10;
    console.log(p.x) // 10
}
getNum(a) 
a.x  // 10
复制代码

以上代码也是把 a 的值复制一份给 p

只不过 a 的值比较特殊,他是一个指向堆区的内存地址,因此p的值也是一个指向同一个堆区的地址。

因此操做 p 的时候 a 也会跟着变化。由于这是在操做同一分内存。

第三种情形

var a = {
    x: 1
}
function getNum(p){
    p = 10;
    console.log(p) // 10
}
getNum(a) 
a.x  // 1
复制代码

这个跟第二种也有点像,也是 a 的内存地址复制了一份给 p

区别是对变量 p 重新赋值了。因此他的修改其实不会影响到 a

扩展 const

经过以上内容是否是就完全搞清楚了值传递究竟是怎么回事了。全部的传递方式其实都是按值传递,只不过有的值是基本类型,有的值是内存地址。

咱们再来延伸一下,ES6 出了一个新的声明变量的方式 const。它能够声明一个常量,而且不能从新声明。也不能修改值。

咱们来看下:

const a = 100;
a = 200;  // error

const b = {x:100}
b = {} //error
b.x = 200; //修改为功
复制代码

咱们经过今天的内存只是来分析下:

其实上const 锁死的是变量 a,你在声明赋值以后他就锁定了那一块栈区的内存。当你赋值的时候其实就是换一块栈区内存空间,因此修改是无效的。

可是若是初始化值是一个对象,咱们知道在栈区它是一个内存地址。虽然咱们没法修改栈区,可是咱们能够修改地址对应的堆区的内容。这也是最后b.x = 200可以修改为功的缘由。

最后

当若是再有人问你 值传递 引用传递 的时候,你能够大声的告诉他,只有一种传递,值传递

啰里啰嗦的写了一堆,文笔很差望见谅。若是有错误或者不足之处,但愿你们指正。若是你读了以后,对你有一点点的帮助,不甚荣幸。

参考连接

developer.mozilla.org/zh-CN/docs/…

相关文章
相关标签/搜索