Olhei em volta para saber como usar o Object.defineProperty
método, mas não consegui encontrar nada decente.
Alguém me deu esse trecho de código :
Object.defineProperty(player, "health", {
get: function () {
return 10 + ( player.level * 15 );
}
})
Mas eu não entendo isso. Principalmente, get
é isso que eu não consigo (trocadilho). Como funciona?
javascript
object
defineproperty
Resfriador de matemática
fonte
fonte
Respostas:
Como você fez uma pergunta semelhante , vamos passo a passo. É um pouco mais longo, mas você pode economizar muito mais tempo do que gastei escrevendo isso:
A propriedade é um recurso de POO projetado para uma separação limpa do código do cliente. Por exemplo, em algumas lojas eletrônicas, você pode ter objetos como este:
Em seguida, no código do seu cliente (a e-shop), você pode adicionar descontos aos seus produtos:
Mais tarde, o proprietário da loja virtual pode perceber que o desconto não pode ser maior do que 80%. Agora você precisa encontrar TODAS as ocorrências da modificação do desconto no código do cliente e adicionar uma linha
Em seguida, o proprietário da loja virtual poderá mudar ainda mais sua estratégia, como "se o cliente for revendedor, o desconto máximo pode ser de 90%" . E você precisa fazer a alteração em vários locais novamente, além de lembrar de alterar essas linhas sempre que a estratégia for alterada. Este é um design ruim. É por isso que o encapsulamento é o princípio básico da OOP. Se o construtor fosse assim:
Então você pode apenas alterar os métodos
getDiscount
( acessador ) esetDiscount
( mutador ). O problema é que a maioria dos membros se comporta como variáveis comuns, apenas o desconto precisa de cuidados especiais aqui. Mas um bom design exige o encapsulamento de todos os membros de dados para manter o código extensível. Então você precisa adicionar muito código que não faz nada. Esse também é um design ruim, um antipadrão padrão . Às vezes, você não pode refatorar os campos para os métodos posteriormente (o código da eshop pode crescer grande ou algum código de terceiros pode depender da versão antiga); portanto, o clichê é menos ruim aqui. Mas ainda assim, é mau. É por isso que as propriedades foram introduzidas em vários idiomas. Você pode manter o código original, basta transformar o membro de desconto em uma propriedade comget
eset
blocos:Observe a última, mas uma linha: a responsabilidade pelo valor correto do desconto foi movida do código do cliente (definição da loja virtual) para a definição do produto. O produto é responsável por manter seus membros de dados consistentes. Um bom design é (grosso modo) se o código funcionar da mesma maneira que nossos pensamentos.
Muito sobre propriedades. Mas o javascript é diferente das linguagens orientadas a objetos puras como C # e codifica os recursos de maneira diferente:
Em C # , transformar campos em propriedades é uma mudança radical ; portanto, os campos públicos devem ser codificados como Propriedades Auto-Implementadas se o seu código puder ser usado no cliente compilado separadamente.
Em Javascript , as propriedades padrão (membro de dados com getter e setter descritas acima) são definidas pelo descritor do acessador (no link que você tem na sua pergunta). Exclusivamente, você pode usar o descritor de dados (para que você não possa usar, por exemplo, valor e definir na mesma propriedade):
Ambos os descritores podem ter estes membros:
for(var i in theObject)
; se falso, não será iterado, mas ainda estará acessível como público* a menos que no modo estrito - nesse caso, o JS interrompe a execução com TypeError, a menos que seja capturado no bloco try-catch
Para ler essas configurações, use
Object.getOwnPropertyDescriptor()
.Aprenda pelo exemplo:
Se você não deseja permitir que o cliente codifique tais truques, pode restringir o objeto em três níveis de confinamento:
Object.isExtensible(<yourObject>)
para verificar se o método foi usado no objeto. A prevenção é superficial (leia abaixo).configurable: false
para todas as propriedades). UseObject.isSealed(<yourObject>)
para detectar esse recurso no objeto. O selo é raso (leia abaixo).writable: false
para todas as propriedades com o descritor de dados). A propriedade gravável do setter não é afetada (pois não possui uma). O congelamento é raso : significa que, se a propriedade for Objeto, suas propriedades NÃO serão congeladas (se desejar, você deverá executar algo como "congelamento profundo", semelhante à clonagem profunda ). UseObject.isFrozen(<yourObject>)
para detectá-lo.Você não precisa se preocupar com isso se escrever apenas algumas linhas divertidas. Mas se você deseja codificar um jogo (como você mencionou na pergunta vinculada), realmente deve se preocupar com o bom design. Tente pesquisar algo no Google sobre antipadrões e cheiro de código . Isso ajudará você a evitar situações como "Ah, preciso reescrever completamente meu código novamente!" , você pode economizar meses de desespero se quiser codificar muito. Boa sorte.
fonte
function Product(name,price) { this.name = name; this.price = price; var _discount; // private member Object.defineProperty(this,"discount",{ get: function() { return _discount; }, set: function(value) { _discount = value; if(_discount>80) _discount = 80; } }); } var sneakers = new Product("Sneakers",20); sneakers.discount = 50; // 50, setter is called sneakers.discount+= 20; // 70, setter is called sneakers.discount+= 20; // 80, not 90! alert(sneakers.discount); // getter is called
get
é uma função que é chamada quando você tenta ler o valorplayer.health
, como em:Efetivamente, não é muito diferente de:
O oposto de get é definido, o que seria usado quando você atribuir ao valor. Como não há levantador, parece que a atribuição à saúde do jogador não é intencional:
Um exemplo muito simples:
fonte
()
para ligar ... Eu não entendo qual foi a ideia quando eles inventaram essa coisa. As funções são totalmente o mesmo: jsbin.com/bugipi/edit?js,console,outputdefineProperty é um método no Object que permite configurar as propriedades para atender a alguns critérios. Aqui está um exemplo simples com um objeto empregado com duas propriedades firstName e lastName e acrescente as duas propriedades substituindo o método toString no objeto.
Você obterá saída como: Jameel Moideen
Vou alterar o mesmo código usando defineProperty no objeto
O primeiro parâmetro é o nome do objeto e, em seguida, o segundo parâmetro é o nome da propriedade que estamos adicionando, no nosso caso, é toString e, em seguida, o último parâmetro é o objeto json, cujo valor será uma função e três parâmetros graváveis, enumeráveis. e configurável. Agora, acabei de declarar tudo como verdadeiro.
Se você executar o exemplo, obterá Saída como: Jameel Moideen
Vamos entender por que precisamos das três propriedades, como gravável, enumerável e configurável.
gravável
Uma parte muito irritante do javascript é, se você alterar a propriedade toString para outra coisa, por exemplo
se você executar isso novamente, tudo será interrompido. Vamos mudar gravável para falso. Se executar o mesmo novamente, você obterá a saída correta como 'Jameel Moideen'. Essa propriedade impedirá a substituição posterior dessa propriedade.
enumerável
se você imprimir todas as chaves dentro do objeto, poderá ver todas as propriedades, incluindo toString.
se você definir enumerável como false, poderá ocultar a propriedade toString de todos os outros. Se executar novamente, você receberá firstName, lastName
configurável
se alguém redefiniu o objeto posteriormente mais tarde, por exemplo, enumerável para true e executá-lo. Você pode ver a propriedade toString veio novamente.
você pode restringir esse comportamento definindo configurável como false.
A referência original dessas informações é do meu blog pessoal
fonte
Basicamente,
defineProperty
é um método que utiliza três parâmetros - um objeto, uma propriedade e um descritor. O que está acontecendo nessa chamada em particular é que a"health"
propriedade doplayer
objeto está sendo atribuída a 10 mais 15 vezes o nível do objeto do jogador.fonte
Sim, não há mais função estendida para o setup setter & getter, este é o meu exemplo Object.defineProperty (obj, name, func)
fonte
Object.defineProperty () é uma função global. Não está disponível dentro da função que declara o objeto de outra forma. Você precisará usá-lo estaticamente ...
fonte
Resumo:
Object.defineProperty
é usado para criar uma nova propriedade no objeto player.Object.defineProperty
é uma função que está presente nativamente no ambiente de tempo de execução JS e usa os seguintes argumentos:Object.defineProperty(obj, prop, descriptor)
O objeto descritor é a parte interessante. Aqui podemos definir o seguinte:
<boolean>
: setrue
o descritor de propriedade puder ser alterado e a propriedade puder ser excluída do objeto. Se configurável,false
as propriedades do descritor transmitidasObject.defineProperty
não podem ser alteradas.<boolean>
: setrue
a propriedade puder ser substituída usando o operador de atribuição.<boolean>
: setrue
a propriedade puder ser iterada em umfor...in
loop. Além disso, ao usar aObject.keys
função, a tecla estará presente. Se a propriedade for,false
elas não serão iteradas usando umfor..in
loop e não serão exibidas ao usarObject.keys
.<function>
: Uma função chamada sempre que a propriedade é necessária. Em vez de fornecer o valor direto, essa função é chamada e o valor retornado é dado como o valor da propriedade<function>
: Uma função que é chamada sempre que a propriedade é atribuída. Em vez de definir o valor direto, essa função é chamada e o valor retornado é usado para definir o valor da propriedade.Exemplo:
fonte
fonte
Define uma nova propriedade diretamente em um objeto ou modifica uma propriedade existente em um objeto e retorna o objeto.
Explicação simples sobre definir Propriedade.
Código de exemplo: https://jsfiddle.net/manoj_antony32/pu5n61fs/
fonte
fonte