javascript传递对象作为参考

Posted

技术标签:

【中文标题】javascript传递对象作为参考【英文标题】:javascript pass object as reference 【发布时间】:2013-05-28 15:22:20 【问题描述】:

我有一个对象,它在函数内的许多不同函数中传递。这些函数可能会也可能不会改变对象的值,但如果他们确实改变了它,那么我想获得对象的最新更改。

以下是我想要做的:

var ob = text: 'this is me', name: 'john'

function (object) 

     changeObject(object);
     customObjectChanger(object);
     callback = function (object) 
          object.text = 'new text';
     

     callback(object);

     // object value here should be objecttext: 'new text', name: 'john';    

【问题讨论】:

javascript 一直自动通过引用传递对象。您是否尝试过上面的代码,看看它是否已经完成了您想要的操作? 不,我没有。我确实读过它。只是想在这里确认一下。 JavaScript Pass By Reference。但是,JavaScript在对象被传递或分配时不会复制对象。因此,它是具有不同名称的 same 对象 - 对对象所做的更改(从任何名称)都会影响所述对象。 这取决于您所说的“通过引用”。在我看来,“同一个对象,不同的名字”就是引用的定义。 @jcsanyi 这就是为什么定义术语和避免歧义很重要。 (***的文章确实承认该术语是模棱两可的,这就是为什么我尝试避免使用“通过引用”,除非明确意味着更改本地名称绑定会影响调用者。) 【参考方案1】:

在 JavaScript 中,对象总是通过复制引用传递。我不确定这是否是完全正确的术语,但会传入对象引用的副本。

这意味着对对象所做的任何更改都将在函数执行完成后对您可见。

代码:

var obj = 
  a: "hello"
;

function modify(o) 
  o.a += " world";


modify(obj);
console.log(obj.a); //prints "hello world"

话虽如此,由于它只是传入的引用的副本,如果您重新分配函数内部的对象,这将在函数之外不可见,因为它只是您更改的引用的副本

代码:

var obj = 
  a: "hello"
;

function modify(o) 
  o = 
    a: "hello world"
  ;


modify(obj);
console.log(obj.a); //prints just "hello"

【讨论】:

en.wikipedia.org/wiki/Evaluation_strategy - 我更喜欢“通过 [对象] 共享调用”,因为它的直接性、实现关注点的分离以及减少与其他调用约定的歧义。 ECMAScript 在规范的任何部分为此目的使用“参考”。 (参考规范类型不适用于函数调用。) +1 可以清楚地描述与传统传递引用的不同之处。 我想我已经明确传递了对象引用的副本,而不是对象本身。 我该如何处理这个问题?如果我想更改对象本身而不是其复制引用怎么办? @Abhinav1602 我想在函数中重新分配一个对象,它的新值在调用函数中可见。【参考方案2】:

“对象”不是 JavaScript 中的值,不能“通过”。

您处理的所有值都是引用(指向对象的指针)。

传递或分配一个引用会给出另一个指向同一个对象的引用。当然,您可以通过其他引用修改同一个对象。

【讨论】:

确实——所以对对象的引用的副本是...“通过”-_- 确实不会传递对象,但会传递引用,如果在接收器函数内部更改属性,您可以修改其属性 简单、简洁的答案。将对象分配给变量时,分配的值是对该对象的引用。所以所有变量都有一个值,但有些值是对对象的引用(例如对象、函数、数组),有些是字面量(例如数字、字符串、布尔值和其他原语)。【参考方案3】:

这是对按值传递和按引用传递 (Javascript) 的更多解释。 在这个概念中,他们谈论的是通过引用传递变量和通过引用传递变量。

按值传递(原始类型)

var a = 3;
var b = a;

console.log(a); // a = 3
console.log(b); // b = 3

a=4;
console.log(a); // a = 4
console.log(b); // b = 3
适用于 JS 中的所有基本类型(字符串、数字、布尔值、未定义、空值)。 a 被分配了一个内存(比如 0x001),b 在内存中创建一个值的副本(比如 0x002)。 因此更改变量的值不会影响另一个变量,因为它们都位于两个不同的位置。

通过引用传递(对象)

var c =  "name" : "john" ;    
var d = c;

console.log(c); //  "name" : "john" 
console.log(d); //  "name" : "john" 

c.name = "doe"; 

console.log(c); //  "name" : "doe"     
console.log(d); //  "name" : "doe" 
JS 引擎将对象分配给变量c,它指向一些内存,比如(0x012) 当d=c时,在这一步中d指向同一个位置(0x012)。 更改两个变量的任何更改值。 函数就是对象

特殊情况,通过引用传递(对象)

c = "name" : "jane"; 
console.log(c); //  "name" : "jane"     
console.log(d); //  "name" : "doe" 
equal(=) 运算符设置新的内存空间或地址

【讨论】:

【参考方案4】:

基本上,在 JavaScript 中,没有 Pass-By-Reference 的概念,因为 Pass-by-value 服务于使 JS 如此特别的目的。当我们在 JavaScript 中传递一个对象时, 1)函数需要带有值,并且该值是参考副本 2)这个值是原始对象的地址。

【讨论】:

【参考方案5】:

我该如何处理这个问题?如果我想更改对象本身而不是其复制引用怎么办?

我想在函数中重新分配一个对象,并且它的新值在调用函数中可见。

为了增加公认的答案,并在那里解决 cmets 中未回答的问题,以下是我对通过参考传递的看法,并在实践中查看 scope / closure:

const obj = 
  count: 0,


function incrementReference(_obj) 
  obj.count++


function createIncrementByCopy(_obj) 
  let inner = 
  Object.assign(inner, _obj)

  return function increment() 
    inner.count++
  


function createScopedIncrement(_obj) 
  return function increment() 
    _obj.count++
  

function createExtend(_obj) 
  return function increment(ext) 
    Object.assign(_obj, ext)
  


console.log('obj', obj) //  count: 0 

incrementReference(obj)
console.log('incrementReference ✅', obj.count) // 1

const incrementCopy = createIncrementByCopy(obj)
incrementCopy()
console.log('incrementCopy ❌', obj.count) // 1

const incrementA = createScopedIncrement(obj)
incrementA()
console.log('incrementA ✅', obj.count) // 2

const extendObj = createExtend(obj)
extendObj( text: 'New Property!' )
console.log('extendObj ✅', obj) //  count: 2, text: 'New Property!'  

下面的文章讨论了一个关于术语的常见混淆,我真的无话可说?https://dev.to/bytebodger/a-gotcha-of-javascript-s-pass-by-reference-1afm

相关(良好的上下文,更复杂,不同的用例):https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign#copying_accessors

【讨论】:

以上是关于javascript传递对象作为参考的主要内容,如果未能解决你的问题,请参考以下文章

在javascript中将对象属性作为指针传递[重复]

如何将对象属性作为参数传递? (JavaScript)

javascript 使用解构分配将对象作为函数的参数传递

在 Symfony2 中使用 Twig 作为 JavaScript 的资产过滤器

Javascript:通过将路径作为字符串传递给对象来从对象中获取深层价值[重复]

Javascript:通过将路径作为字符串传递给对象来从对象中获取深层价值[重复]