为传递给JavaScript中的函数的对象分配新值

我是 JavaScript的新手(尽管在C中经验丰富),今天我写了这样的东西:
function foo(bar) {
    bar = "something else";
}
var x = "blah";
foo(x);
alert(x); // Alerts with "blah",but I was expecting it to alert with "something else"

这让我很困惑,因为我一直在观看道格拉斯·克罗克福德的一些JavaScript视频,并记得他说像“JavaScript总是通过引用传递”.

我可以解释这种情况的方式是JavaScript传递对象的引用,但这些引用被复制.这意味着在foo函数中,我正在为bar分配一个新的引用,然后超出范围,留下引用x保持不变.基本上我们从:

x   ---->"blah"

然后当调用foo时,bar引用相同的数据:

x   ---->"blah"
bar -----^

所以,当“其他”分配给bar时,会发生这种情况:

x   ---->"blah"
bar ---->"something else"

这是JavaScript中实际发生的事情的准确模型,还是我错过了其他内容

作为一个额外的问题,有没有办法说,更改此变量引用的数据?这种情况经常出现,还是可以轻易避免?

编辑:

道格拉斯·克罗克福德在video I watched中说“对象总是通过引用传递它们不是通过值传递”,这是正确的,但函数的参数是通过值传递的,它只是通过值传递引用.

解决方法

“JavaScript始终通过引用传递”是,[白色]谎言和术语混淆.虽然有一些“灰色区域”,但我去了 these definitions of evaluation strategies.

这是我的论点和推理.如果您持有不同的视图,请确保您至少可以支持它.

Call By Reference

Call By Reference意味着(对许多人来说)分配给参数会影响调用者中的绑定.

In call-by-reference evaluation (also referred to as pass-by-reference),a function receives an implicit reference to a variable used as argument,rather than a copy of its value. This typically means that the function can modify (i.e. assign to) the variable used as argument—something that will be seen by its caller.

这不是JavaScript的情况,因为原始帖子在观察到的行为中已经注意到了.重新分配参数(可以将其视为具有动态提供的值的局部变量)不会影响任何提供的参数.

有时,“参考呼叫”[混淆]用于表示“通过共享呼叫”或“参考号值的呼叫”,如下所述; true Call By Reference可以在C和VB等语言中找到,但不能在JavaScript中找到.

Call By [Object] Sharing

JavaScript的调用约定可以完全按照Call By [Object] Sharing语义进行讨论.

所有JavaScript对象都是值;并且所有原始值(所有值的子集)都是不可变的.

The semantics of call by sharing differ from call by reference in that assignments to function arguments within the function aren’t visible to the caller,so e.g. if a variable was passed,it is not possible to simulate an assignment on that variable in the caller’s scope. However since the function has access to the same object as the caller (no copy is made),mutations to those objects,if the objects are mutable,within the function are visible to the caller,which may appear to differ from call by value semantics.

在ultrayoshi的答案中提供了这些共享突变的一个例子,并且可以简单地解释:当表达式(例如变量访问)评估对象,并且所述对象被传递给函数时,不进行复制/克隆.

Call By Value [of the Reference]

虽然术语“通过参考值调用值”通常用于描述行为,但应注意Java / C#意义上的JavaScript does not have “references”(或“非参考”值),因此该术语具有微妙的误导性 – 至少它不是说Call By Reference,它有各种各样的内涵,很多人都理解一个低解释.

In call-by-value,the argument expression is evaluated,and the resulting value is bound to the corresponding variable in the function .. If the function or procedure is able to assign values to its parameters,only its local copy is assigned — that is,[any variable] passed into a function call is unchanged in the caller’s scope when the function returns.

因为只传递对象的“引用”(而不是所述对象的复制/克隆),所以语义仅仅是Call By Sharing的语义.但是,我在JavaScript中避免使用这个术语,因为它带来了不必要的实现细节,并且还介绍了实现如何传递对象与原始值之间的区别.

The description “call-by-value where the value is a reference” is common (but should not be understood as being call-by-reference); another term is call-by-sharing.

因此,当我谈论在JavaScript中调用约定时,

我更喜欢使用Call By Sharing来讨论行为,并且我避免Call By [Value / Reference],因为它们有太多不同的“含义”并拖入不必要的实现细节.

相关文章

前言 做过web项目开发的人对layer弹层组件肯定不陌生,作为l...
前言 前端表单校验是过滤无效数据、假数据、有毒数据的第一步...
前言 图片上传是web项目常见的需求,我基于之前的博客的代码...
前言 导出Excel文件这个功能,通常都是在后端实现返回前端一...
前言 众所周知,js是单线程的,从上往下,从左往右依次执行,...
前言 项目开发中,我们可能会碰到这样的需求:select标签,禁...