Passagem de parâmetro por referência

2,072 views
Skip to first unread message

Bissu

unread,
Apr 14, 2011, 10:23:53 AM4/14/11
to js.pro
Senhores,

estive pesquisando estes dias sobre passagem de parâmetros por
referência em funções Javascript. Inevitavelmente descobri que a
passagem em si (como os famosos ponteiros em C) não acontecem.
Pesquisei um pouco e para quem estiver interessado segue o resumo da
explicação e a referência.

Ao passar valores em funções javascript, a referência é totalmente
perdida pelo novo contexto. Como no exemplo abaixo:

function swop(a, b){
var c = a;
a = b;
b = c;
}

No final da execução deste código, a e b ainda terão seus valores
originais.

O problema pode ser contornado se você usar um objeto (que
empiricamente parece manter a referência original) para fazer a troca
de valores.

var A = new Array();

function swop(A, a, b){
var c = A[a];
A[a] = A[b];
A[b] = c;
}

Se você popular este vetor e passar os índices, os elementos irão
trocar de posição.

fonte: http://snook.ca/archives/javascript/javascript_pass

Quem conhecer outros métodos, por favor, posta aí.

Abraço,
Henrique.

Thiago Hiromi Santana

unread,
Apr 14, 2011, 11:12:14 AM4/14/11
to js...@googlegroups.com, Bissu
2011/4/14 Bissu <bis...@gmail.com>
Henrique,

Boa explicação. Já tinha esquecido que isso existia. Mas isso não é uma prática muito comum - pelo menos pra mim, e julgando o todo pela parte - aos utilizadores de JS. 

Eu costumo usar variáveis "globais" - mas sempre me lembrando de usar (function(){/*execucao*/})(); pra não zonear as variáveis da janela - quando quero mudar esse valor dentro de uma função ao invés de utilizar a passagem de parâmetros por referência.

abs.

Thiago Hiromi Santana
Web Developer

Marcelo Henrique

unread,
Apr 14, 2011, 12:45:01 PM4/14/11
to Thiago Hiromi Santana, js...@googlegroups.com
Pois é,

enquanto eu estudava aqui aprendi a usar esse (function(){/*execucao*/})(); O problema é que minha variável ia ser lida como chamada de outra função, ela não tinha como ser declarada global direto no JS, aê tive que me virar com o apply dentro da função que utilizava.

Henrique



2011/4/14 Thiago Hiromi Santana <thiago...@gmail.com>

Johann Vivot

unread,
Apr 14, 2011, 1:40:48 PM4/14/11
to js...@googlegroups.com, Marcelo Henrique, Thiago Hiromi Santana
Existe uma forma de sobrescrever o método this do javascript.

var that = this;
function swop(that, a, b){
       var c = that.a;
       that.a = that.b;
       that.b = c;
}

É muito utilizado para trabalhar referenciando elementos em js.

Abs,

Johann Luschnic Vivot
johan...@gmail.com
+55 11 6446-1244 | +55 11 7338-4359
http://gordao.net/

Thiago Hiromi Santana

unread,
Apr 14, 2011, 2:17:02 PM4/14/11
to Johann Vivot, js...@googlegroups.com, Marcelo Henrique
2011/4/14 Johann Vivot <johan...@gmail.com>

Johann,

eu chamo isso [1] de mudar o 'this' do JS. não 'that'. rs

abs

Johann Vivot

unread,
Apr 14, 2011, 3:17:40 PM4/14/11
to Thiago Hiromi Santana, js...@googlegroups.com, Marcelo Henrique
Não estamos mudando nada, apenas é uma forma de gravar um contexto.

Na minha opinião (e pelo que vejo por aí), sobrescrever o this é a forma mais elegante de resolvermos esse problema de passagem de contextos. Assim conseguimos manter facilmente a referencia sem POG.

;)

Abs,

Johann Luschnic Vivot
johan...@gmail.com
+55 11 6446-1244 | +55 11 7338-4359
http://gordao.net/




Luciano Ramalho

unread,
Apr 15, 2011, 9:38:52 AM4/15/11
to js...@googlegroups.com, Bissu
2011/4/14 Bissu <bis...@gmail.com>:

Henrique, grato por sua contribuição!

O estilo de passagem de parâmetros por referência em JavaScript é o
mesmo que existe em Python, Ruby e muitas outras linguagens.

O que acontece com este código é o seguinte:

function swop(a, b){
       var c = a;
       a = b;
       b = c;
}

Quando vocẽ escreve a = b o que você está fazendo é criar uma "nova"
referência de nome "a", e atribuindo a ela o valor de b. A melhor
forma de entender isso é esquecer a velha metáfora de que variáveis
são receptáculos onde se armazena valores. Em linguagens que trabalham
com referências, como JavaScript, Python, Ruby, as variáveis não são
receptáculos, elas são rótulos que apontam para objetos que já existem
na memória antes mesmo da atribuição acontecer. Isso vale inclusive
para as variáveis de objetos em Java (mas não para as variáveis
primitivas, tipo int etc). Portanto a atribuição não representa
colocar um valor em um container, mas sim associar um símbolo a um
valor.

Eu tenho uns slides que exemplificam isso, em Python, mas a idéia é a
mesma em JavaScript:

http://www.slideshare.net/ramalho/python-a-primeira-mordida-presentation

Veja os slides 57, 58 e 59.

Preciso fazer um podcast para explicar porque o audio é essencial...

--
Luciano Ramalho
programador repentista || stand-up programmer
Twitter: @luciano

Marcelo Henrique

unread,
Apr 20, 2011, 1:32:47 AM4/20/11
to Luciano Ramalho, js...@googlegroups.com
Pô Luciano,

apoio total ao podcast réré. Quando fizer manda o link aí.

Dei uma olhada nos slides. Não sabia sobre essa questão dos rótulos e apelidos. Realmente uma abordagem diferente.

Mas, referente a troca de contextos, a única forma de mudar um o valor por referência seria passando um marcador global ou criando um objeto para ele?



Henrique



2011/4/15 Luciano Ramalho <luc...@ramalho.org>

Luciano Ramalho

unread,
Apr 20, 2011, 7:13:29 PM4/20/11
to Marcelo Henrique, js...@googlegroups.com
2011/4/20 Marcelo Henrique <bis...@gmail.com>:

> Pô Luciano,
> apoio total ao podcast réré. Quando fizer manda o link aí.
> Dei uma olhada nos slides. Não sabia sobre essa questão dos rótulos e
> apelidos. Realmente uma abordagem diferente.
> Mas, referente a troca de contextos, a única forma de mudar um o valor por
> referência seria passando um marcador global ou criando um objeto para ele?

Sim, a única forma de mudar é passando um objeto ou usando uma variável global.

Agora, essa dificuldade na verdade é uma coisa boa. É bem documentado
o fato de que funções que alteram objetos externos a seu escopo são a
causa de muitos bugs difíceis de resolver. Inclusive algumas
linguagens funcionais mais "puras", como Haskell e Erlang,
praticamente proibem a mutabilidade, ou apenas permitem que ela ocorra
em contextos muito restritos.

Muitas vezes a pasagem de estruturas para serem manipuladas por
funções é uma forma de otimização prematura. O mais seguro é
simplesmente passar cópias dos valores. Note que em JavaScript,
Python, Ruby e Java, por exemplo, as strings são imutáveis. Vocé não
consegue substituir os caracteres de uma string por outros, apenas
consegue criar uma nova string a partir da transformação dos
caracteres de outra, entende? Isso é diferente do que acontece em C e
Pascal. Mas não é ruim, a maior parte do tempo a gente nem percebe.

Veja por exemplo os docs oficiais do método String.replace:

https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String/replace

Primeira linha:

Returns a new string with some or all matches of a pattern replaced by
a replacement.

Ou seja, o método replace não muda a string, devolve uma nova string.

Na dúvida, essa é a melhor forma de implementar as suas funções.

Iraê

unread,
Apr 21, 2011, 11:41:19 AM4/21/11
to js.pro
Também sou fã de podcast. Apoio total.

Não posso prometer quando, mas topo participar de episódios no futuro
pra contribuir =)

On Apr 20, 8:13 pm, Luciano Ramalho <luci...@ramalho.org> wrote:
> 2011/4/20 Marcelo Henrique <bis...@gmail.com>:
>
> > Pô Luciano,
> > apoio total aopodcastréré. Quando fizer manda o link aí.
> > Dei uma olhada nos slides. Não sabia sobre essa questão dos rótulos e
> > apelidos. Realmente uma abordagem diferente.
> > Mas, referente a troca de contextos, a única forma de mudar um o valor por
> > referência seria passando um marcador global ou criando um objeto para ele?
>
> Sim, a única forma de mudar é passando um objeto ou usando uma variável global.
>
> Agora, essa dificuldade na verdade é uma coisa boa. É bem documentado
> o fato de que funções que alteram objetos externos a seu escopo são a
> causa de muitos bugs difíceis de resolver. Inclusive algumas
> linguagens funcionais mais "puras", como Haskell e Erlang,
> praticamente proibem a mutabilidade, ou apenas permitem que ela ocorra
> em contextos muito restritos.
>
> Muitas vezes a pasagem de estruturas para serem manipuladas por
> funções é uma forma de otimização prematura. O mais seguro é
> simplesmente passar cópias dos valores. Note que em JavaScript,
> Python, Ruby e Java, por exemplo, as strings são imutáveis. Vocé não
> consegue substituir os caracteres de uma string por outros, apenas
> consegue criar uma nova string a partir da transformação dos
> caracteres de outra, entende? Isso é diferente do que acontece em C e
> Pascal. Mas não é ruim, a maior parte do tempo a gente nem percebe.
>
> Veja por exemplo os docs oficiais do método String.replace:
>
> https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/...
Reply all
Reply to author
Forward
0 new messages