O JavaScript continua me surpreendendo e essa é outra instância. Acabei de encontrar um código que não entendi a princípio. Então, eu depurei e cheguei a esta descoberta:
alert('a'['toUpperCase']()); //alerts 'A'
Agora isso deve ser óbvio se toUpperCase()
for definido como um membro do tipo string, mas inicialmente não fazia sentido para mim.
De qualquer forma,
- isso funciona porque
toUpperCase
é um membro de 'a'? Ou há algo mais acontecendo nos bastidores? o código que eu estava lendo tem uma função da seguinte maneira:
function callMethod(method) { return function (obj) { return obj[method](); //**how can I be sure method will always be a member of obj** } } var caps2 = map(['a', 'b', 'c'], callMethod('toUpperCase')); // ['A','B','C'] // ignoring details of map() function which essentially calls methods on every // element of the array and forms another array of result and returns it
É meio que uma função genérica chamar QUALQUER método em QUALQUER objeto. Mas isso significa que o método especificado já será um membro implícito do objeto especificado?
Estou certo de que estou perdendo algum entendimento sério do conceito básico de funções JavaScript. Por favor, ajude-me a entender isso.
javascript
function
Mahesha999
fonte
fonte
arr[5]
. Se os números de onde os nomes de identificador válido que você poderia usar a notação de ponto:arr.5
.5['toString']()
.Respostas:
Para quebrar.
.toUpperCase()
é um método deString.prototype
'a'
é um valor primitivo, mas é convertido em sua representação de objetoassim
é o acesso via notação de colchete na propriedade
toUpperCase
, deString.prototype
. Como essa propriedade faz referência a um método , podemos invocá-lo anexando()
fonte
foo.bar
efoo['bar']
são iguais, então o código que você postou é o mesmo queAo usar
foo[bar]
(observe a falta de aspas), você não usa o nome literal,bar
mas qualquer valor que a variávelbar
contenha. Portanto, o uso dafoo[]
notação em vez defoo.
permite que você use um nome de propriedade dinâmico.Vamos dar uma olhada em
callMethod
:Primeiro de tudo, ele retorna uma função que recebe
obj
como seu argumento. Quando essa função é executada, ele chamamethod
esse objeto. Portanto, o método fornecido apenas precisa existir emobj
si mesmo ou em algum lugar de sua cadeia de protótipos.Caso
toUpperCase
esse método venhaString.prototype.toUpperCase
- seria estúpido ter uma cópia separada do método para cada string existente.fonte
Você pode acessar os membros de qualquer objeto com
.propertyName
notação ou["propertyName"]
notação. Essa é a característica da linguagem JavaScript. Para ter certeza de que o membro está no objeto, basta verificar se está definido:fonte
Basicamente, o javascript trata tudo como um objeto, ou melhor, todo objeto pode ser visto como um dicionário / matriz associativa. E funções / métodos são definidos exatamente da mesma maneira para o objeto - como uma entrada nessa matriz associativa.
Então, essencialmente, você está referenciando / chamando (observe a propriedade ' () ') 'toUpperCase', do objeto 'a' (que é um tipo de string, neste caso).
Aqui está um código do topo da minha cabeça:
fonte
anyObject['anyPropertyName']
é o mesmo deanyObject.anyPropertyName
quandoanyPropertyName
não há caracteres problemáticos.Consulte Trabalhando com objetos , no MDN.
O
toUpperCase
método está anexado ao tipo String. Quando você chama uma função em um valor primitivo, aqui'a'
, ela é automaticamente promovida a um objeto, aqui uma String :Você pode ver a função existente registrando-se
String.prototype.toUpperCase
.fonte
Então, em Javascript,
objects
sãoobjects
. Isso é que eles são desta natureza{}
. As propriedades do objeto podem ser definidas usando um destes:a.greeting = 'hello';
oua['greeting'] = 'hello';
. Os dois lados funcionam.A recuperação funciona da mesma maneira.
a.greeting
(sem aspas) é'hello'
,a['greeting']
é'hello'
. Exceção: se a propriedade for um número, apenas o método bracket funcionará. O método de ponto não.Então,
'a'
é um objeto com'toUpperCase'
propriedade que é realmente uma função. Você pode recuperar a função e chamá-la posteriormente de qualquer maneira:'a'.toUpperCase()
ou'a'['toUpperCase']()
.Mas, na melhor das hipóteses, a melhor maneira de escrever a função de mapa seria:
var caps = ['a','b','c'].map( function(char) { return char.toUpperCase(); } )
Quem precisa da
callMethod
função?fonte
Todo objeto JavaScript é uma tabela de hash, portanto, você pode acessar seus membros especificando uma chave. por exemplo, se uma variável for uma sequência, ela deverá ter a função toUpperCase. Então, você poderia invocá-lo
então, por str embutido, você poderia ter abaixo
fonte
toUpperCase é um método javascript padrão: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/String/toUpperCase
O motivo pelo qual funciona
'a'['toUpperCase']()
é que a função toUpperCase é uma propriedade do objeto string'a'
. Você pode fazer referência às propriedades em um objeto usandoobject[property]
ouobject.property
. A sintaxe 'a''toUpperCase' indica que você está referenciando a propriedade 'toUppercase' do objeto de string 'a' e, em seguida, chamando-o ().fonte
Não. Alguém poderia passar um objeto que
toUpperCase
; outoUpperCase
que não é uma funçãoNo primeiro caso, um erro será gerado porque o acesso a uma propriedade que não existe retorna
undefined
e não podemos invocarundefined
como uma função.No segundo caso, um erro será gerado porque, novamente, não podemos chamar uma não-função como uma função.
Lembre-se de que o JavaScript é uma linguagem muito pouco digitada. Pouca ou nenhuma verificação de tipo ocorre, a menos e até que seja necessário. O código que você mostrou funciona em certos casos, porque, nesses casos, o objeto passado tem uma propriedade chamada
toUpperCase
, que é uma função.O fato de o
obj
argumento não ter garantia dos tipos corretos de propriedades não incomoda o JavaScript, por assim dizer. Adota uma atitude de "esperar para ver" e não gera um erro até que um problema real ocorra no tempo de execução.fonte
Quase tudo em javascript pode ser tratado como um objeto. No seu caso, o próprio alfabeto atua como um objeto de string e
toUpperCase
pode ser chamado como seu método. Os colchetes são apenas uma maneira alternativa de acessar as propriedades do objeto e, comotoUpperCase
é um método, o simplebracket()
é necessário ao lado da['toUpperCase']
formação['toUpperCase']()
.'a'['toUpperCase']()
é equivalente a'a'.toUpperCase()
fonte
O importante a ser observado aqui é que, como o Javascript é uma linguagem dinâmica , todo objeto é, essencialmente, apenas um mapa de hash glorificado ( com algumas exceções ). E tudo em um objeto Javascript pode ser acessado de duas maneiras - notação entre colchetes e notação de ponto.
Analisarei rapidamente as duas anotações que respondem à primeira parte da sua pergunta e depois chegarei à segunda parte.
Notação de colchete
Este modo é mais semelhante ao acesso a hashmaps e matrizes em outras linguagens de programação. Você pode acessar qualquer componente (dados (incluindo outros objetos) ou função) usando esta sintaxe.
É exatamente isso que você está fazendo no seu exemplo. Você tem
'a'
, que é uma string (e não um caractere literal, como seria em uma linguagem como C ++).Usando a notação de colchete, você acessa seu
toUpperCase
método. Mas acessá-lo ainda não é suficiente; simplesmente digitaralert
, por exemplo, em Javascript, não chama o método É apenas uma afirmação simples. Para chamar a função, é necessário adicionar o parêntese:alert()
mostra uma caixa de diálogo simples contendoundefined
, pois não recebeu parâmetros. Agora podemos usar esse conhecimento para decifrar seu código, que se torna:O que é muito mais legível.
Na verdade, uma boa maneira de entender isso um pouco melhor é executar o seguinte Javascript:
Isso chama
alert
passando um objeto de função, tambémalert
, sem também executar o segundo alerta. O que é mostrado (no Chrome 26, pelo menos) é o seguinte:A ligar:
mostra duas caixas de mensagens consecutivas contendo
undefined
. Isso é fácil de explicar: o interioralert()
é executado primeiro, mostraundefined
(porque não tinha nenhum parâmetro) e não retorna nada. O alerta externo recebe o valor de retorno do alerta interno - o que não é nada e também é exibidoundefined
em uma caixa de mensagem.Experimente todos os casos no jsFiddle!
Notação de ponto
Essa é a abordagem mais padrão, que permite que membros de um objeto sejam acessados usando o
.
operador dot ( ). É assim que seu código ficaria na notação de ponto:Muito mais legível. Então, quando devemos usar a notação de ponto e quando devemos usar a notação entre colchetes?
Comparação
A principal diferença entre os dois métodos é semântica. Há também outros detalhes, mas chegarei a esses em um segundo. O mais importante é o que você realmente deseja fazer - uma regra geral é que você use notação de ponto para campos e métodos bem estabelecidos que um objeto possui e a notação de colchete para quando você estiver realmente usando seu objeto como um mapa de hash .
Um ótimo exemplo de por que essa regra é tão importante pode ser mostrado em seu exemplo - como o código está usando a notação de colchete em um local onde a notação de pontos teria sido muito mais sensata, torna o código mais difícil de ler. E isso é uma coisa ruim, porque o código é lido muito mais vezes do que está escrito .
Em alguns casos, você deve usar a notação de colchete, mesmo que a notação de ponto seja mais sensata:
se um membro de um objeto tiver um nome contendo um ou mais espaços ou qualquer outro caractere especial, você não poderá usar a notação de ponto:
foo.some method()
não funciona, masfoo["some method"]()
funciona;se você precisar acessar dinamicamente os membros de um objeto, também ficará preso usando a notação de colchete;
Exemplo:
A linha inferior é que você deve usar a sintaxe de colchete ao usar o objeto como um mapa de hash (
foods["burger"].eat()
) e a sintaxe de ponto ao trabalhar com campos e métodos "reais" (enemy.kill()
). Com o Javascript sendo uma linguagem dinâmica, a linha entre os campos e métodos "reais" de um objeto e "outros" dados armazenados pode ficar bastante embaçada. Mas contanto que você não os misture de maneiras confusas, você ficará bem.Agora, vamos ao resto da sua pergunta (finalmente!: P).
Você não pode. Tente. Tente chamar
derp
uma string. Você receberá um erro nas linhas de:Sim, no seu caso, teria que ser. Caso contrário, você terminará com o erro mencionado acima. No entanto, você não precisa usar
return obj[method]();
acallMethod()
função Você pode adicionar sua própria funcionalidade que depois será usada pela função de mapa. Aqui está um método codificado que transforma todas as letras em uma letra maiúscula:O código no tutorial ao qual você vinculou usa funções parciais . Eles são um conceito complicado por si mesmos. Ler mais sobre esse assunto deve ajudar a tornar as coisas mais claras do que eu jamais poderia torná-las.
Nota: este é o código da função de mapa usado pelo código na pergunta, fonte aqui .
fonte
Se você está perguntando como realmente funciona, é assim que eu o leio. Ok, esta é uma função matemática simples. Para entendê-lo, você precisa olhar para a tabela ascii. O que atribui um valor numérico a cada letra. Para encobri-lo, a competição simplesmente usa uma declaração lógica para encobri-lo, por exemplo, If (ChcrValue> 80 && charValue <106) // Este é o conjunto de letras minúsculas e charValue = charValue - 38; // a distância entre o conjunto inferior e o conjunto superior
é simples assim, eu realmente não me incomodei em procurar os valores corretos, no entanto, isso está basicamente mudando todas as letras minúsculas para o valor maiúsculo.
fonte
'a'['toUpperCase']()
trabalhar. Mas o mal-entendido é compreensível, se alguém não leu a pergunta.text-transform: uppercase
foi adicionado, eu estava no fim de como JS conseguiu mudar o caso, tirou a dúvida e aprendeu uma coisa ou duas. Muito obrigado.