Recentemente, encontrei uma pergunta interessante: "Os valores em JS são aprovados por valor ou por referência?"
Antes de analisar esse problema, precisamos entender o que é chamado pelo valor e o que é chamado por referência. Na ciência da computação, essa parte é chamada de estratégia de avaliação. Ele determina como os valores são passados entre variáveis, entre parâmetros reais e parâmetros formais ao chamar uma função.
Passe por valor vs. Passe por referência
Chamada por valor é a estratégia de avaliação mais usada: os parâmetros formais de uma função são cópias dos parâmetros reais passados quando chamados. A modificação do valor de um parâmetro formal não afetará o parâmetro real.
Ao passar por referência (chamada por referência), os parâmetros formais da função recebem uma referência implícita do parâmetro real, em vez de uma cópia. Isso significa que, se o valor do parâmetro da função for modificado, o parâmetro real também será modificado. Ambos apontam para o mesmo valor.
A passagem por referência torna o rastreamento das chamadas de função mais difícil e às vezes causa alguns bugs sutis.
Passar por valor Como as réplicas são clonadas a cada vez, o desempenho é menor para alguns tipos complexos. Ambos os métodos de passagem de valores têm seus próprios problemas.
Vamos primeiro olhar para um exemplo C para entender a diferença entre passar por valor e referência:
A cópia do código é a seguinte:
Void Modify (int p, int * q)
{
p = 27; // Pass P por valor é uma cópia do parâmetro real A, apenas P é modificado
*Q = 27; // q é uma referência a B, e q e b são modificados
}
int main ()
{
int a = 1;
int b = 1;
Modificar (a, & b); // um passe por valor, B Pass por referência,
// a não mudou, B mudou
retornar (0);
}
Aqui podemos ver:
a => Quando P é passado por valor, a modificação do valor do parâmetro formal P não afeta o parâmetro A, P é apenas uma cópia de a.
B => Q é passado por referência. Ao modificar o valor do parâmetro formal q, também afeta o valor do parâmetro real b.
Explore como o valor do JS é passado
O tipo básico de JS é passado por valor.
A cópia do código é a seguinte:
var a = 1;
função foo (x) {
x = 2;
}
foo (a);
console.log (a); // ainda 1, não afetado pela atribuição de x = 2
Vejamos o objeto:
A cópia do código é a seguinte:
var obj = {x: 1};
função foo (o) {
Ox = 3;
}
foo (obj);
console.log (obj.x); // 3, modificado!
Explique O e OBJ são o mesmo objeto, e O não é uma cópia do OBJ. Portanto, não é passado por valor. Mas isso significa que os objetos JS são passados por referência? Vejamos os seguintes exemplos:
A cópia do código é a seguinte:
var obj = {x: 1};
função foo (o) {
o = 100;
}
foo (obj);
console.log (obj.x); // Still 1, OBJ não foi modificado para 100.
Se for passado por referência, modificando o valor do parâmetro formal O, deve afetar o parâmetro real. Mas modificar o valor de O aqui não afeta o OBJ. Portanto, os objetos em JS não são passados por referência. Então, como o valor do objeto será passado em JS?
Passe a chamada compartilhando
Para ser preciso, os tipos básicos em JS são passados por valores e os tipos de objetos são passados compartilhando (chamado compartilhando, também chamado pelo objeto e compartilhado por objeto). Foi proposto pela primeira vez por Barbara Liskov. Na língua Glu de 1974. Essa estratégia de avaliação é usada em Python, Java, Ruby, JS e outros idiomas.
O objetivo dessa estratégia é que, quando uma função passa por argumentos, a função aceita uma cópia da referência de argumento real do objeto (nem uma cópia do objeto passada pelo valor, nem uma referência implícita passada por referência). A diferença entre ele e a passagem por referência é que a atribuição de parâmetros de função em um passe compartilhado não afetará o valor do parâmetro real. Como no exemplo a seguir, o valor do OBJ não pode ser modificado modificando o valor do parâmetro formal o.
A cópia do código é a seguinte:
var obj = {x: 1};
função foo (o) {
o = 100;
}
foo (obj);
console.log (obj.x); // Still 1, OBJ não foi modificado para 100.
No entanto, embora a referência seja uma cópia, o objeto referenciado é o mesmo. Eles compartilham o mesmo objeto, portanto, modificar o valor do atributo do objeto de parâmetro formal também afetará o valor do atributo do parâmetro real.
A cópia do código é a seguinte:
var obj = {x: 1};
função foo (o) {
Ox = 3;
}
foo (obj);
console.log (obj.x); // 3, modificado!
Para tipos de objetos, como o objeto é mutável, a modificação do próprio objeto afetará o compartilhamento da cópia de referência e referência do objeto. Para os tipos básicos, como ambos são imutáveis, não há diferença entre passar por compartilhar e passar por valor (chamada por valor), de modo que os tipos básicos do JS estão alinhados com a passagem pelo valor e de acordo com a passagem pelo compartilhamento.
A cópia do código é a seguinte:
var a = 1; // 1 é o número do tipo, imutável var b = a; b = 6;
De acordo com a estratégia de avaliação aprovada pelo compartilhamento, A e B são duas referências diferentes (B é uma cópia de referência de A), mas faz referência ao mesmo valor. Como o tipo básico número 1 aqui é imutável, não há diferença entre a passagem pelo valor e a passagem pelo compartilhamento aqui.
Propriedades imutáveis dos tipos básicos
Os tipos básicos são imutáveis e apenas objetos são mutáveis. Por exemplo, valores numéricos 100, valores booleanos são verdadeiros, falsos e modificando esses valores (por exemplo, transformar 1 em 3 e transformar verdadeiro em 100) não faz sentido. O que é mais fácil de entender mal é a corda em JS. Às vezes, tentamos "mudar" o conteúdo da string, mas em JS, qualquer operação "modificar" que parece ser um valor de string está realmente criando um novo valor de string.
A cópia do código é a seguinte:
var str = "abc";
str [0]; // "a"
str [0] = "D";
str; // ainda "abc"; A tarefa é inválida. Não há como modificar o conteúdo da string
O objeto é diferente, o objeto é variável.
A cópia do código é a seguinte:
var obj = {x: 1};
obj.x = 100;
var o = obj;
Ox = 1;
obj.x; // 1, modificado
o = true;
obj.x; // 1, não mudará devido a o = true
Aqui a variável OBJ é definida, o valor é objeto e, em seguida, o valor da propriedade Obj.x é definido como 100. Em seguida, defina outra variável O e o valor ainda é esse objeto. Neste momento, os valores das duas variáveis Obj e O apontam para o mesmo objeto (compartilhando uma referência ao mesmo objeto). Portanto, modificar o conteúdo do objeto tem um impacto no OBJ e no. No entanto, o objeto não é passado por referência. O valor de O é modificado por O = true e não afetará o OBJ.