Existe alguma maneira de obter algo como o seguinte para trabalhar em JavaScript?
var foo = {
a: 5,
b: 6,
c: this.a + this.b // Doesn't work
};
No formulário atual, esse código obviamente gera um erro de referência, pois this
não se refere a foo
. Mas é Existe alguma maneira de ter valores nas propriedades de um objeto de literais dependem de outras propriedades declarado anteriormente?
javascript
object-literal
kpozin
fonte
fonte
foo.a
oufoo.b
forem alterados, o valor defoo.c
também mudará no sincronismo. Isso pode ou não ser o necessário.this
se liga ao objeto aninhado mais profundo. Por exemplo:... x: { get c () { /*this is x, not foo*/ } } ...
foo
hoje vem sendo declarado como uma variável ec
só será avaliada no momento em que é invocado, usandofoo
interiorc
irá funcionar, ao contrário dethis
(ser embora cuidado)Você poderia fazer algo como:
Isso seria algum tipo de inicialização única do objeto.
Observe que você está realmente atribuindo o valor de retorno de
init()
parafoo
, portanto, você precisareturn this
.fonte
delete this.init
antes,return this
para quefoo
não seja poluído.init()
chamada foi anexada diretamente ao literal para mantê-lo como uma expressão única. Mas é claro que você pode chamar a função separadamente, se desejar.A resposta óbvia e simples está faltando, portanto, para ser completo:
Não. Todas as soluções aqui adiam para depois que o objeto é criado (de várias maneiras) e depois atribuem a terceira propriedade. A maneira mais simples é fazer isso:
Todos os outros são apenas maneiras mais indiretas de fazer a mesma coisa. (O Felix's é particularmente inteligente, mas requer a criação e destruição de uma função temporária, adicionando complexidade; e deixa uma propriedade extra no objeto ou [se você tiver
delete
essa propriedade] afeta o desempenho dos acessos subsequentes à propriedade nesse objeto.)Se você precisar que tudo esteja dentro de uma expressão, poderá fazer isso sem a propriedade temporária:
Ou, é claro, se você precisar fazer isso mais de uma vez:
então onde você precisa usá-lo:
fonte
this
está disponível apenas para métodos desse objeto e nenhum outro tipo de propriedades. Alguma idéia de onde eu poderia encontrar isso? Obrigado!delete
é 10% mais rápida e a lagartixa:delete
é apenas 1% mais lenta.Instancie simplesmente uma função anônima:
fonte
new Point(x, y)
exceto que a função não é nomeada para reutilização.var foo = function() { this.…; return this; }.call({});
que não é sintaticamente muito diferente, mas semanticamente saudável.new
palavra - chave.Agora no ES6, você pode criar propriedades em cache lento. No primeiro uso, a propriedade avalia uma vez para se tornar uma propriedade estática normal. Resultado: na segunda vez que a sobrecarga da função matemática é ignorada.
A mágica está no caos.
Na seta, o captador
this
pega o escopo lexical circundante .fonte
Object.defineProperty(foo, 'c', {get:function() {...}})
para defini-las. Isso é facilmente feito de uma maneira discreta em uma fábrica como esta. Obviamente, se você pode usar oget
açúcar, é mais legível, mas a capacidade existe.Algum fechamento deve lidar com isso;
Todas as variáveis declaradas em
foo
são privadasfoo
, como seria de esperar em qualquer declaração de função e, como todas elas estão no escopo, todas elas têm acesso uma à outra sem precisar se referirthis
, da mesma forma que você esperaria com uma função. A diferença é que essa função retorna um objeto que expõe as variáveis privadas e atribui esse objetofoo
. No final, você retorna apenas a interface que deseja expor como um objeto com areturn {}
instruçãoA função é então executada no final com a
()
qual faz com que todo o objeto foo seja avaliado, todas as variáveis em instanciadas e o objeto de retorno adicionados como propriedades defoo()
.fonte
Você poderia fazer assim
Esse método se mostrou útil quando tive que me referir ao objeto em que uma função foi originalmente declarada. A seguir, é apresentado um exemplo mínimo de como eu o usei:
Ao definir self como o objeto que contém a função de impressão, você permite que a função se refira a esse objeto. Isso significa que você não precisará 'vincular' a função de impressão a um objeto se precisar passá-la para outro lugar.
Se preferir, use
this
como ilustrado abaixoEm seguida, o código a seguir registrará 0, 1, 2 e, em seguida, dará um erro
Ao usar o método self, você garante que a impressão sempre retornará o mesmo objeto, independentemente do contexto em que a função é executada. O código acima funcionará perfeitamente e registrará 0, 1, 2 e 3 ao usar a versão própria do
createMyObject()
.fonte
Para concluir, no ES6, temos aulas (suportadas no momento em que escrevemos isso apenas pelos navegadores mais recentes, mas disponíveis no Babel, TypeScript e outros transpilers)
fonte
Você pode fazer isso usando o padrão do módulo. Assim como:
Com esse padrão, você pode instanciar vários objetos foo de acordo com sua necessidade.
http://jsfiddle.net/jPNxY/1/
fonte
}();
, ela executaria e retornaria automaticamente um objeto, não uma função. Além disso,foo.c
é uma função, portanto, escrever nele trechos que funcionem e a próxima chamada viafooObject.c()
falhará. Talvez esse violino esteja mais próximo do que você procura (também é um singleton, não projetado para ser instanciado).Existem várias maneiras de conseguir isso; isto é o que eu usaria:
fonte
apenas por uma questão de pensamento - coloque as propriedades do objeto fora de uma linha do tempo:
também existem respostas melhores acima . Foi assim que modifiquei o código de exemplo que você questionou.
ATUALIZAR:
fonte
var foo = { get a(){return 5}, get b(){return 6}, get c(){return this.a + this.b} }
agora você pode apenas fazerfoo.c
em vez defoo.c()
:) (Sinta-se livre para colar isso em sua resposta de modo a formatação é melhor!)Criar nova função no literal do seu objeto e chamar um construtor parece um desvio radical do problema original e é desnecessário.
Você não pode fazer referência a uma propriedade irmão durante a inicialização literal do objeto.
A solução mais simples para propriedades calculadas é a seguir (sem heap, sem funções, sem construtor):
fonte
As outras respostas postadas aqui são melhores, mas aqui está uma alternativa que:
init()
ou código fora do literal do objetoFunções anônimas auto-executáveis e armazenamento de janela
O pedido é garantido (
bar
antesbaz
).Polui
window
, é claro, mas não consigo imaginar alguém escrevendo um script que exijawindow.temp
persistência. TalveztempMyApp
se você é paranóico.Também é feio, mas ocasionalmente útil. Um exemplo é quando você está usando uma API com condições rígidas de inicialização e não deseja refatorar, para que o escopo esteja correto.
E está seco, é claro.
fonte
A chave para tudo isso é o escopo .
Você precisa encapsular o "pai" (objeto pai) da propriedade que deseja definir como seu próprio objeto instanciado e, em seguida, pode fazer referências às propriedades dos irmãos usando a palavra-chave
this
É muito, muito importante lembrar que, se você se referir
this
sem fazê-lo primeiro,this
se referirá ao escopo externo ... que será owindow
objeto.fonte
se seu objeto é escrito como uma função que retorna um objeto E você usa os métodos de atributo de objeto do ES6, é possível:
fonte
Eu uso o seguinte código como alternativa e funciona. E a variável também pode ser matriz. (@ Fausto R.)
fonte
Aqui está uma maneira elegante do ES6:
Eu o uso para fazer algo assim:
fonte
Que tal essa solução também funcionará com objetos aninhados com matriz
fonte
Jogando em uma opção desde que eu não vi esse cenário exato coberto. Se você não deseja
c
atualizar quandoa
oub
atualizar, um ES6 IIFE funciona bem.Para minhas necessidades, eu tenho um objeto que se relaciona com uma matriz que acabará sendo usada em um loop, então eu só quero calcular algumas configurações comuns uma vez, então é isso que eu tenho:
Como eu preciso definir uma propriedade para
indexOfSelectedTier
e preciso usar esse valor ao definir ahasUpperTierSelection
propriedade, eu calculo esse valor primeiro e o passo como parâmetro para o IIFEfonte
Outra abordagem seria declarar o objeto primeiro antes de atribuir propriedades a ele:
Com isso, você pode usar o nome da variável do objeto para acessar os valores já atribuídos.
Melhor para
config.js
arquivo.fonte
foo
que aponta para o objeto em questão.Isso é quase idêntico à resposta do @ slicedtoad, mas não usa uma função.
fonte
Aqui estavam usando expressões de classe para obter a interface literal do objeto aninhado que desejaríamos. Esta é a próxima melhor coisa que o IMHO pode fazer para referenciar as propriedades de um objeto durante a criação.
O principal a notar é que, ao usar esta solução, você tem exatamente a mesma interface que teria de um literal de objeto. E a sintaxe está bem próxima do literal de um objeto (vs usando uma função, etc).
Compare o seguinte
Solução que propus
Solução se os literais do objeto fossem suficientes
Outro exemplo
Aqui nesta classe, você pode combinar vários caminhos relativos entre si, o que não é possível com um objeto literal.
fonte
Se você deseja usar JS nativo, as outras respostas fornecem boas soluções.
Mas se você estiver disposto a escrever objetos de referência própria como:
Eu escrevi uma biblioteca npm chamada objeto auto-referenciado que suporta essa sintaxe e retorna um objeto nativo.
fonte
b
valor de propriedade deve ser:${this.a + this.a}
. Segundo, mas menos importante, você gostaria de retornar um número, não uma string usando algo comoparseInt
. Por último e mais importante, quando tentei esse exemplo, ele simplesmente não funciona, pelo mesmo motivo que o OP está perguntando. Osthis
retornos indefinidos quando usados sua própria declaração de objeto. @ alex-e-leon