javascript参数类型-清除javascript参数值传递

2023-08-29 0 9,047 百度已收录

清除javascript参数值传递

参数传递是指在调用函数时向函数传递配置或运行参数的行为,包括通过call和apply传递值。

在实际开发中,我们总结javascript参数传递分为按值传递的基本数据类型(String、Numbe、Boolean、Null、undefind)和按引用传递的引用数据类型(Object,包括Array、Function、Data)。 本文旨在纠正这种误读:本质上引用类型是通过共享传递的。

在探讨传值问题之前,我们先来看看javascript在声明变量时是如何分配显存的

原始类型将原始值存储在堆栈上。 引用类型就是在堆中保存数据,然后在栈中构建对堆地址的引用。 在javascript中,是不允许直接访问存储在堆内存中的对象的,所以在访问对象的时候,首先获取的是该对象在堆内存中的地址javascript参数类型,然后根据这个地址来获取值在对象中,这就是传说中的引用访问。 原始类型的值是可以直接访问的。 不同的显存分配机制也带来不同的访问机制。

复制变量时基本类型和引用类型之间也存在差异:

所以我们得出结论,javascript中所有函数参数都是按值传递的,数组复制到左值,但是对于基本数据类型复制的是原始值,对于引用类型复制的是堆内存的地址。

这些引用类型的评估策略是callbysharing。

理清了理论知识后,我们就举几个例子来具体情况分析一下。

基本数据类型的传值

let a = 1
function foo(x) {
    console.log(x)
}
foo(a)
console.log(a)
// 2
// 1

变量a的值直接复制到foo函数的形参x中,变量x是变量a的副本。 它们独立地将值'1'存储在各自的上下文堆栈中,并且互不影响。 我们对 a 和 x 的读写操作对它们各自的值进行操作。

在示例图中,值 1 分别保存在全局上下文和 foo 的上下文中。

按引用类型传递值

let a = {
    abc: 1
}
function foo(x) {
    x.abc = 2
    console.log(x.abc)
}
foo(a)
console.log(a.abc)
// 2
// 2

根据编码经验javascript参数类型,我们会得出里面的栗子是通过引用传递的结论,这是非常错误的。 对象a的引用被传递到函数foo内部,函数的内部变量x指向全局变量a,然后传递引用,所以变量x和变量a读写同一个对象。 我们用一张图来说明:

但也许通过分享。 通过引用传递是我们对javascript求值策略的误解。 如果通过引用传递,下面的反例是无知的:

let a = {
    abc: 1
}
function foo(x) {
    console.log(x) // {abc: 1}
    x = 2
    console.log(x) // 2
}
foo(a)
console.log(a.abc) // 1

执行 foo 函数时,第一个副本输出“{abc:1}”,第二个副本输出“2”,调用 foo 函数后的 console.log(a.abc) 语句输出“1”。

通过引用传递的单词。 表达式 console.log(a.abc) 在 foo 函数执行后执行。 此时a应该已经参数化为2,a.abc不存在,应该复制输出'undefind'。 并且打印出1,说明在foo函数内部执行x=2并没有改变内部对象a的值。

为什么会出现a和x指向同一个对象后,对于x形参,原对象的值没有改变?

由于这里传递给左值的对象是通过共享调用(callbysharing),根据复制引用类型变量的特点(前面介绍过):

执行foo函数时,数组x的值为传入的对象a的显存地址引用,即在变量对象创建阶段,x保存的是一个对象的堆显存地址。 此时a和x都指向同一个对象。 然后在函数的执行阶段,代码的第二行将原始数据类型2形参赋予x,导致x不再保存原始堆内存地址,而是保存一个原始值。 当再次访问x时,就是最后一次访问x形参的原始值。

所以给x的形参会改变上下文栈中标识符x保存的具体值

这时候如果采用引用传递的话,变量a指向的对象也应该被参数化为2。但是x形参似乎是基本数据类型,并没有让原对象变成字面值,这就表示引用类型不是按值按引用传递,值的写入不按照按引用的规则进行处理。

需要区分赋予对象属性形参和直接赋予对象形参的区别:

let a = {
    abc: 1
}
function foo(x) {
    x.abc = 99
    console.log(x) // {abc: 99}
    x = 2
    console.log(x) // 2
}
foo(a)
console.log(a) // {abc: 99}

在 foo 函数内更改对象 x 的属性将导致 x 和 a 所指向的对象发生更改,因为它们指向相同的堆地址。

参考:

《Javascript中级编程》

JavaScript 传递参数

JS 是按值传递还是按引用传递?

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

悟空资源网 javascript javascript参数类型-清除javascript参数值传递 https://www.wkzy.net/game/175669.html

常见问题

相关文章

官方客服团队

为您解决烦忧 - 24小时在线 专业服务