ti-enxame.com

Uma função Javascript retorna objetos por referência ou valor por padrão?

Eu tenho um objeto definido fora da função, em um escopo global. Este objeto não é passado para a função como argumento, mas a função o modifica e retorna o objeto modificado.

O que eu queria saber é se a função retorna uma cópia do objeto ou o objeto global original?

Além disso, passar esse objeto para a função como argumento fará alguma diferença, pois os objetos são passados ​​para as funções por referência?

20
Hammad Akhwand

Sempre que você retornar um objeto, retornará uma referência ao objeto. Da mesma forma, quando você está passando um objeto, está passando uma referência. No entanto, passar um objeto como argumento pode ser diferente do que apenas alterar um objeto no escopo global, como mostram esses exemplos. Isso ocorre porque a referência ao objeto é transmitida por valor.

Se você estiver alterando os membros de um objeto, se você o passa como argumento ou apenas atualiza o objeto global não faz diferença. De qualquer maneira, você está trabalhando com o mesmo objeto.

Exemplo 1:

var object = {foo:'original'};

function changeObject() {
    object.foo = 'changed';
    return object;
}

console.log(changeObject()); // outputs {foo:'changed'}
console.log(object); // outputs {foo:'changed'}

Exemplo 2:

var object = {foo:'original'};

function changeArgument(object) {
    object.foo = 'changed';
    return object;
}

console.log(changeArgument(object));  // outputs {foo:'changed'}
console.log(object);  // outputs {foo:'changed'}

Por outro lado, se você estiver substituindo o objeto por um novo objeto, a alteração não persistirá se você fizer isso no argumento, mas persistirá se você fizer isso no objeto global. Isso ocorre porque o argumento passa a referência ao objeto por valor. Depois de substituir esse valor por uma referência a um novo objeto, você não está mais falando do mesmo objeto.

Exemplo 3:

var object = {foo:'original'};

function replaceObject() {
    object = {foo:'changed'};
    return object;
}

console.log(replaceObject()); // outputs {foo:'changed'}
console.log(object); // outputs {foo:'changed'}

Exemplo 4:

var object = {foo:'original'};

function replaceArgument(object) {
    object = {foo:'changed'};
    return object;
}

console.log(replaceArgument(object)); // outputs {foo:'changed'}
console.log(object); // outputs {foo:'original'}
45
Tim Goodman

Pode ser um comentário tardio, mas esse é um desafio típico em qualquer idioma. Objetos criados na pilha e transmitidos por referência e não por primitivas (por valor). Penso que a raiz da questão é instância compartilhada versus instância única para evitar efeitos indesejados. Por exemplo, chamamos uma função para obter um modelo (objeto) para o novo usuário adicionar à coleção ou desejar limpar o formulário no evento cancel de diferentes módulos para começar de novo. É fácil de entender e fácil de ignorar. Casos de teste geralmente não cobrem todas as permutações de uso

A lista de verificação de sanidade:

Aqui a instância compartilhada:

var bigo = {
    usr: { name: 'steven' },
    bigi: function () {
        return this.usr;
    }
};   
var outA = bigo.bigi();
var outB = bigo.bigi();

print(outA.name); // => steven
print(outB.name); // => steven

outA.name = 'ilan'; // change value

print(outA.name); // => ilan
print(outB.name); // => ilan

Instância não compartilhada:

var bigo = {
    bigi: function () {
        var user = { name: 'steven' };
        return user;
    }
};   

var outA = bigo.bigi();
var outB = bigo.bigi();

print(outA.name); // => steven
print(outB.name); // => steven

outA.name = 'ilan'; // change value

print(outA.name); // => ilan
print(outB.name); // => steven
2
algor

O que eu queria saber é se a função retorna uma cópia do objeto ou o objeto global original?

Efetivamente, você só lida com referências a objetos em JavaScript. Até var foo = {} apenas atribui uma referência a um novo objeto para foo.

1
Quentin

Se o objeto estiver fora da função, você não precisará 'devolvê-lo'. Se você modificar o objeto dentro da função, ele atualizará o próprio objeto. Em seguida, você pode fazer referência ao objeto recém-atualizado em outras funções, conforme necessário.

1
LoneWolfPR

Da sua pergunta, é assim que eu acho que seu código se parece (mais ou menos):

var o = {};

function f() {
    o.prop = true;
    return o;
}
  1. Nesse caso, a variável global o faz referência a um objeto.
  2. Quando você modifica o, modifica qualquer referência de o. Portanto, ele modifica o objeto original.
  3. Quando você retorna o, está retornando uma referência ao objeto original.

Passar o objeto para uma função resulta na referência ao objeto original que está sendo passado. Portanto, qualquer modificação afetará o objeto original. Por exemplo:

var o = {};

f(o);

console.log(o.prop); // true

function f(o) {
    o.prop = true;
}
1
Aadit M Shah