Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

FK.

[Resolvido] Valor de oculto de this

Recommended Posts

Iaew galera,

Estou lendo "O melhor do javascript", e tem a seguinte função bastante usada lá:

 

Function.prototype.method = function(name, func) {
   this.prototype[name] = func;
   return this;
};

 

De acordo com o livro, uma função interna de uma função externa, tem seu valor this para o objeto global(inclusive ele cita que isso foi um erro da linguagem e ensina como contornar esse erro). No entanto, estou confuso com essa função acima. Esse this é associado ao objeto global(que acredito que seja Object.prototype) ou a esse objeto Function ? Esse "Function" é um objeto construtor ?

 

Tenho uma outra dúvida também. Toda vez que tentamos associar um valor a uma propriedade que não existe em um objeto, ela é criada imediatamente, e isso pode ser feito usando a notação "." ou o "[]". Por exemplo:

 

  myObject.newProperty = 'Value'; // Funciona
  myObject['otherNewProperty'] = 'NewValue'; // Funciona

 

No entanto, a segunda linha da primeira função que citei (this.prototype[name] = func), só funciona dessa forma, e não usando o ".", ou seja, isso não funciona(pelo menos no meu browser):

 

  this.prototype.name = func; // Porque não funciona ???

 

Valeu galera !!

 

Edit --

 

Nem notem que eu errei grandão no título do tópico :/

Compartilhar este post


Link para o post
Compartilhar em outros sites
inclusive ele cita que isso foi um erro da linguagem e ensina como contornar esse erro
desculpe, mas explique melhor isso.

não concordo com essa afirmação.

 

 

Esse "Function" é um objeto construtor ?

hein!? isso não existe.

Construtor é um método de um objeto, e não um objeto.

 

 

No entanto, a segunda linha da primeira função que citei (this.prototype[name] = func), só funciona dessa forma, e não usando o ".", ou seja, isso não funciona(pelo menos no meu browser):

pq em javascript não existe o conceito de "variavel variavel" (não que eu saiba pelo menos).

Compartilhar este post


Link para o post
Compartilhar em outros sites

desculpe, mas explique melhor isso.

não concordo com essa afirmação.

 

Crie um objeto. Esse objeto tem uma propriedade com seu valor associado a uma função literal, e essa função literal, talvez por ser muito grande, tenha outras funções aninhadas dentro dela, e essas funções internas aninhadas, terão seu valor this associado ao objeto global, por erro da linguagem. Por exemplo:

 

   var Objeto = function() {
       this.nome = 'Fernando';
       this.mostrarNome = function() {
           alert(this.nome);
           var apenasTeste = function() {
               alert(this.nome); // Esse this está associado ao objeto global. Por erro da linguagem.
           };
           apenasTeste();
       };
   };
   var objeto1 = new Objeto();
   objeto1.mostrarNome();

 

Teste você mesmo. Agora como contornar isso ?

O javascript tem o escopo de função, ou seja, toda variável ou parâmetro tem sua visibilidade apenas dentro de uma função. Nenhuma função externa pode acessar variáveis de uma função interna, porém uma função interna tem acesso aos parâmetros e variáveis da função externa, EXCETO this e arguments. Então para contornar o erro, na função externa, vamos criar uma variável e atribuir o valor this para ela, que por convenção seu nome é that. Reconstruindo o exemplo acima:

 

var Objeto = function() {
       this.nome = 'Fernando';
       this.mostrarNome = function() {
           alert(this.nome);
           var that = this;
           var apenasTeste = function() {
               alert(that.nome); // Agora irá funcionar da maneira ESPERADA.
           };
           apenasTeste();
       };
   };
   var objeto1 = new Objeto();
   objeto1.mostrarNome();

 

hein!? isso não existe.

Construtor é um método de um objeto, e não um objeto.

 

Eu também não entendi, mas já vi exemplos usando esse Function para criar novas funções, que se não me engano é parecido com isso:

 

   Sintaxe do Function: new Function([arg1[, arg2[, ... argN]],] CorpoDaFuncao)

   var minhaFuncao = new Function("a", "b", "return a + b");
   document.writeln(minhaFuncao(5, 2));

 

Ao meu ver, não deixar de ser um construtor, pois estamos usando a keyword new. Talvez eu possa estar errado, não sei, é por isso que estou aqui.. :D

 

pq em javascript não existe o conceito de "variavel variavel" (não que eu saiba pelo menos).

 

Vou pesquisar sobre esse conceito de variavel variavel, pois já vi em PHP, talvez seja por isso mesmo que não funcione no javascript, e qualquer coisa eu já posto aqui. Mas se não me engano, eu acho que tem, sei la. :D

Compartilhar este post


Link para o post
Compartilhar em outros sites
this.prototype.name = func; // Porque não funciona ???

Simplificadamente, não funciona pq essa construção referencia a propriedade 'name' do objeto prototype de Function.

Ao fazer

this.prototype[name]

primeiramente name, que é uma variável, neste contexto, é avaliada, retornando a string informada como parâmetro.

Se você fizer:

(new Function).method('meuMetodo', function () { alert('bla!'); });

então

this.prototype[name]

assumirá

this.prototype['meuMetodo']

que é a mesma coisa que:

this.prototype.meuMetodo

 

Compartilhar este post


Link para o post
Compartilhar em outros sites

Espera, this.prototype.name, esse name também não seria avaliado com o valor meuMetodo também ? Estou um pouco confuso :(

 

Além disso, esse this está referenciando a quem nesse caso ? O prototype de Object ou de Function ?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Vamos lá galera, ajudem a dar um [Resolvido] neste tópico. Assim ajudaremos futuramente alguém. :D

Compartilhar este post


Link para o post
Compartilhar em outros sites
Espera, this.prototype.name, esse name também não seria avaliado com o valor meuMetodo também ? Estou um pouco confuso

Leia novamente o que eu postei, está bem explicado...

Se você fizer obj.name, espera-se que haja uma propriedade name dentro de obj.

Se você fizer obj.[name], primeiro avalia-se name, que pode conter uma string com o nome de uma propriedade de obj.

 

obj.meuMetodo

é o mesmo que

name = 'meuMetodo';
obj[name];

 

Além disso, esse this está referenciando a quem nesse caso ? O prototype de Object ou de Function ? 						 						

Se você está fazendo this dentro de uma função, refere-se a ela.

A menos que você use os métodos call ou apply, this se refere sempre ao contexto em que se encontra.

Compartilhar este post


Link para o post
Compartilhar em outros sites

De acordo com o livro, uma função interna de uma função externa, tem seu valor this para o objeto global(inclusive ele cita que isso foi um erro da linguagem e ensina como contornar esse erro).

 

Não sei o contexto em que o cara afirmou isso, mas da forma que você colocou aqui no tópico, o erro está no texto do cara, não na linguagem. De fato, se o cara realmente fez essa afirmação, ele cara afirmou desconhecer a linguagem:

 

Esse this é associado ao objeto global(que acredito que seja Object.prototype) ou a esse objeto Function ?

 

1. Se o código da função é um código strict, defina ThisBinding como thisArg.

2. Senão, se thisArg for null ou undefined, defina ThisBinding como o objeto global.

3. Senão, se Type(thisArg) não for Object, defina ThisBinding como ToObject(thisArg).

4. Senão, defina ThisBinding como thisArg.

 

Esse "Function" é um objeto construtor ?

 

O construtor de Function é, ele mesmo, um objeto Function e sua propriedade interna [[Class]] é "Function". O valor da propriedade interna [[Prototype]] do construtor de Function é o objeto prototype padrão de Function (15.3.4).

 

O valor da propriedade interna [[Extensible]] do construtor de Function é true.

 

Tenho uma outra dúvida também. Toda vez que tentamos associar um valor a uma propriedade que não existe em um objeto, ela é criada imediatamente, e isso pode ser feito usando a notação "." ou o "[]".

 

Os objetos ECMAScript são como uma matriz associativa, com pares propriedade=valor:

 

var myPropertyName = "name";

var o = {};
o[myPropertyName] = "João Neto";
o.myPropertyName = "outro valor";

console.log(o.myPropertyName); //outro valor
console.log(o[myPropertyName]); //João Neto
console.log(o.name); //João Neto

 

Quando você utiliza a notação de pontos, você está dizendo que o identificador do lado direito é, literalmente, o nome da propriedade. Por outro lado, ao utilizar a notação de colchetes, a expressão dentro dos colchetes será interpretada e seu resultado será definido como o nome da propriedade.

 

No primeiro caso:

 

1. o[myPropertyName] = "João Neto";

2. o["name"] = "João Neto";

3. o.name = "João Neto";

 

No segundo caso:

 

1. o.myPropertyName = "outro valor";

Compartilhar este post


Link para o post
Compartilhar em outros sites
Não sei o contexto em que o cara afirmou isso, mas da forma que você colocou aqui no tópico, o erro está no texto do cara, não na linguagem. De fato, se o cara realmente fez essa afirmação, ele cara afirmou desconhecer a linguagem

 

Acredito que o contexto seja de funções construtoras. Sério, pegue esse código e teste ele:

 

 

<!DOCTYPE html>
<html>
   <head>
       <meta charset="UTF-8" />
       <title>Meu titulo</title>
       <script type="text/javascript">
           var Objeto = function() {
               this.nome = 'Fernando';
               this.mostrarNome = function() {
                   alert(this.nome);
                   var apenasTeste = function() {
                       alert(this.nome);
                   };
                   apenasTeste();
               };
           };
           var objeto1 = new Objeto();
           objeto1.mostrarNome();
       </script>
   </head>
   <body>

   </body>
</html>

 

 

Quando executa mostrarNome() parece que deverá ser lançado um alert com o nome Fernando duas vezes, no entanto, na segunda vez é undefined. Porque de acordo com o autor, Douglas Crockford, uma função interna aninhada a função externa, tem o valor this associado ao objeto global.

 

Edit: Ele também diz que essa metodologia de criar objetos não é recomendada, já que, essas propriedades do objeto são todas públicas. Uma melhor forma para deixar tudo privado, era devolvendo um objeto depois da execução de uma função, isso é, usando o closure:

 

var myObject = function(x, y) {
   var nome = 'Fernando';
   return {
       somar: function() {
           return x + y;
       },
       getNome: function() {
           return nome;
       }
   };
}(10, 5);
document.writeln(myObject.somar()); // 15
document.writeln(myObject.getNome()); // Fernando
document.writeln(myObject.nome); // Undefined
// Não é útil tão útil esse código, mas foi apenas para exemplo.

 

Como retornei um objeto que tem uma função somar() e getNome(), não tenho acesso direto a variável nome. Mas essas funções tem acesso ao parâmetros e variaveis da função externa, inclusive nome. xD

 

Quando você utiliza a notação de pontos, você está dizendo que o identificador do lado direito é, literalmente, o nome da propriedade. Por outro lado, ao utilizar a notação de colchetes, a expressão dentro dos colchetes será interpretada e seu resultado será definido como o nome da propriedade.

 

Entendiii, tudo depende do valor interno da variável, quando avaliado dentro de colchetes certo ?

 

Como você lá em cima atribuiu 'name' para myPropertyName, então quando avaliado dentro dos colchetes, uma nova propriedade com o nome 'name' será criada nesse objeto né ? Então por isso eu usar a notação o.name depois funciona, já que essa propriedade agora foi criada. No entanto, removendo a primeira linha após a criação do objeto vazio, o[myPropertyName] = 'João Neto', se eu tentar usar a notação o.name, irá retornar undefined. Mas enfim, acredito que entendi agora !!!

 

O Hugo explicou isso lá em cima, no entanto, não compreendi da forma que ele disse. :(

 

Vlw

Compartilhar este post


Link para o post
Compartilhar em outros sites

pegue esse código e teste ele:

 

Não preciso testar, Fernando, a especificação é bastante clara sobre isso.

 

Quando executa mostrarNome() parece que deverá ser lançado um alert com o nome Fernando duas vezes, no entanto, na segunda vez é undefined. Porque de acordo com o autor, Douglas Crockford, uma função interna aninhada a função externa, tem o valor this associado ao objeto global.

 

É como eu disse, esse "parece que deverá" mostra total desconhecimento. Não de sua parte, é claro, uma vez que é notório que está estudando e ainda não conhece, mas desconhecimento por parte do autor do livro, que não deixou claro para você que está estudando o que é especificado. De fato, ele te confundiu ao passar uma opinião pessoal dele, como se fosse um "erro da linguagem".

 

Leia novamente meu post, principalmente essa parte:

 

...

2. Senão, se thisArg for null ou undefined, defina ThisBinding como o objeto global.

...

 

Como pode ver, não tem absolutamente NADA a ver com "uma função interna aninhada a função externa", se thisArg for undefined, ThisBinding receberá o objeto global em uma função com código não strict. Simples assim.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Então acredito que seja melhor eu ler essa especificação. xD

 

Agora fiquei com algumas dúvidas:

 

O que é esse thisArg e thisBinding, pois não vi no javascript. :(

 

Além disso, o ECMAScript é uma linguagem de programação? Uma "linguagem-base"? Uma especificação?

 

Eu estudar ECMAScript é mesma coisa que eu javascript ?

 

Talvez o autor quis diferenciar isso da especificação, talvez para tornar o entendimento mais claro. Mas eu nunca concordo com nenhum autor só porque tem um nome ou faz parte de alguma coisa. A especificação é sempre a definição. Eu queria muito ler ela, mas não entendo muito inglês ainda. :(

 

Mas sim, ele diz que foi um ERRO DE PROJETO DA LINGUAGEM, achei isso muito estranho.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Agora fiquei com algumas dúvidas:

 

O que é esse thisArg e thisBrinding, pois não vi no javascript.

 

Isso ai é interno, faz parte da especificação. Você realmente não verá "externamente" na linguagem, é apenas a especificação de "como as coisas devem acontecer".

 

Além disso, o ECMAScript é uma linguagem de programação? Uma "linguagem-base"? Uma especificação?

 

Eu estudar ECMAScript é mesma coisa que eu javascript ?

 

Essa especificação Ecma é baseada em diversas tecnologias, sendo o JavaScript (Netscape) e JScript (Microsoft) as mais conhecidas. A linguagem foi inventada por Brendan Eich na Netscape e apareceu pela primeira vez no navegador Netscape 2.0 dessa empresa. Ela apareceu em todos os navegadores subsequentes da Netscape e em todos os navegadores da Microsoft a partir da versão 3.0.

 

O desenvolvimento dessa especificação iniciou em Novembro de 1996. A primeira edição dessa especificação Ecma foi aprovada pela Assembleia Geral Ecma de Junho de1997.

 

Aquela especificação Ecma foi enviada para a ISO/IEC JTC 1 para aprovação em âmbito de processo rápido, e foi aprovada como a especificação internacional ISO/IEC 16262 em Abril de 1998. A Assembleia Geral Ecma de Junho de 1998 aprovou a segunda edição da ECMA-262 para mantê-la totalmente alinhada com a ISO/IEC 16262. As mudanças entre a primeira e segunda edição são de natureza editorial.

 

A terceira edição da especificação introduziu poderosas expressões regulares, melhor manipulação de strings, novas declarações de controle, try/catch para manipulação de exceções, definição mais rigorosa de erros, formatação para saída numérica e outras pequenas mudanças em antecipação à uma futura internacionalização e crescimento da linguagem. A terceira edição da especificação ECMAScript foi aprovada pela Assembleia Geral Ecma de Dezembro de 1999 e publicada como ISO/IEC 16262:2002 em Junho de 2002.

 

Desde a publicação da terceira edição, ECMAScript tem recebido uma adoção maciça na World Wide Web, onde se tornou a linguagem de programação que é suportada por praticamente todos os navegadores. Um trabalho significativo foi feito para desenvolver uma quarta edição da ECMAScript. Mas esse trabalho não foi completado e não foi publicado como a quarta edição da ECMAScript. A presente quinta edição da ECMAScript (publicada como ECMA-262 5th edição) codifica de facto interpretações da especificação da linguagem que tornaram-se comum nas implementações dos navegadores e adiciona suporte para novos recursos que surgiram desde a publicação da terceira edição. Tais recursos incluem propriedades de acesso, criação reflexiva e inspeção de objetos, controle de atributos de propriedades, funções adicionais para manipulação de Array, suporte para o formato de codificação de objetos JSON e um strict mode que fornece uma maior verificação de erros e segurança do programa.

 

ECMAScript é uma linguagem vibrante e sua evolução não está completa. Melhoramentos técnicos significantes continuarão em futuras edições dessa especificação.

 

Nota: Por favor, note que ECMAScript edição 4 para a numeração padrão "ECMA-262 Edição 4" da Ecma foi reservada, mas não usada no processo de publicação Ecma. Portanto, "ECMA-262 Edição 4" como uma publicação Ecma International não existe.

 

Talvez o autor quis diferenciar isso da especificação, talvez para tornar o entendimento mais claro. Mas eu nunca concordo com nenhum autor só porque tem um nome ou faz parte de alguma coisa. A especificação é sempre a definição.

 

Uma implementação em conformidade de ECMAScript precisa fornecer e suportar todos os tipos, valores, objetos, propriedades, funções, sintaxe de programa e semânticas descritas nessa especificação

 

Uma implementação em conformidade com esse padrão internacional deve interpretar caracteres em conformidade com o padrão Unicode, versão 3.0 ou posterior e ISO/IEC 10646-1, com UCS-2 ou UTF-16, como forma a de codificação adotada, nível 3. Se o subconjunto ISO/IEC 10646-1 adotado não for, de outra forma, espeficidado, então é presumido que seja o subconjunto BMP, coleção 3. Se o formato de codificação adotado não for, de outra forma, especificado, então é presumido que seja a codificação UTF-16.

 

É permitido que uma implementação em conformidade de ECMAScript suporte sintaxe de programa e expressão regular não descrita nessa especificação. Em particular, é permitido que uma implementação em conformidade de ECMAScript suporte sintaxe de programa que faça uso de "palavras reservadas para uso futuro" listada na seção 7.6.1.2 dessa especificação.

 

Eu queria muito ler ela, mas não entendo muito inglês ainda.

 

Como pode ver nos quotes que fiz nesse tópico, estou traduzindo toda a especificação. Assim que a tradução estiver pronta, a publicarei aqui no fórum e no portal iMasters.

 

;)

Compartilhar este post


Link para o post
Compartilhar em outros sites

Nossa cara, valeu ! Percebi que tenho que ficar atento as conclusões ;)

 

Só espero não ter sido chato com ninguém :(

 

Poxa, muito da hora isso, você traduzindo toda a especificação !

 

Valeu mesmo !

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.