Atualmente, estou transformando de Java para Javascript, e é um pouco difícil para mim descobrir como estender os objetos da maneira que eu quero.
Eu já vi várias pessoas na internet usarem um método chamado estender no objeto. O código ficará assim:
var Person = {
name : 'Blank',
age : 22
}
var Robot = Person.extend({
name : 'Robo',
age : 4
)}
var robot = new Robot();
alert(robot.name); //Should return 'Robo'
Alguém sabe como fazer isso funcionar? Ouvi dizer que você precisa escrever
Object.prototype.extend = function(...);
Mas não sei como fazer esse sistema funcionar. Se não for possível, mostre-me outra alternativa que estenda um objeto.
extend
função, eu configurar um exemplo aqui: jsfiddle.net/k9LRdRespostas:
Você deseja 'herdar' do objeto de protótipo da Pessoa:
fonte
Person()
construtor está sendo chamado quando você faz issonew Robot()
? Parece-me que você deve chamar esse construtor da classe base em vez de fazerthis.name = name;
noRobot()
construtor ...Person.apply(this, arguments);
. Também seria melhor usar emRobot.prototype = Object.create(Person.prototype);
vez denew Person();
.Mundo sem a "nova" palavra-chave.
E mais simples sintaxe "tipo prosa" com Object.create ().
* Este exemplo é atualizado para as classes ES6.
Primeiro, lembre-se de que o Javascript é uma linguagem prototípica . Não é baseado em classe. Portanto, escrever em forma de protótipo expõe sua verdadeira natureza e pode ser muito simples, parecido com uma prosa e poderoso.
TLDR;
Não, você não precisa de construtores, nenhuma
new
instanciação ( leia por que você não deve usarnew
), nãosuper
, nada engraçado__construct
. Você simplesmente cria objetos e depois os estende ou transforma.( Se você souber sobre getters e setters, consulte a seção "Leitura adicional" para ver como esse padrão oferece getters e setters gratuitos da maneira que o Javascript originalmente pretendia, e quão poderosos eles são .)
Sintaxe em forma de prosa: protótipo de base
À primeira vista, parece muito legível.
Extensão, criando um descendente de
Person
* Os termos corretos são
prototypes
e os delesdescendants
. Não háclasses
e não há necessidadeinstances
.Uma maneira de fornecer uma maneira "padrão" de criar a
descendant
é anexando um#create
método:As maneiras abaixo têm menor legibilidade:
Compare com o equivalente "clássico":
A legibilidade do código usando o estilo "clássico" não é tão boa.
Classes ES6
É certo que alguns desses problemas são erradicados pelas classes ES6, mas ainda assim:
Ramificação do protótipo de base
Anexar métodos exclusivos para
Robot
Verificando herança
Você já tem tudo o que precisa! Sem construtores, sem instanciação. Prosa limpa e clara.
Leitura adicional
Gravabilidade, configurabilidade e getters e setters gratuitos!
Para getters e setters gratuitos, ou configuração extra, você pode usar o segundo argumento de Object.create (), conhecido como propertiesObject. Também está disponível em # Object.defineProperty e # Object.defineProperties .
Para ilustrar o quão poderoso isso é, suponha que queremos que todos
Robot
sejam estritamente feitos de metal (viawritable: false
) e padronizepowerConsumption
valores (via getters e setters).E todos os protótipos de
Robot
não podem sermadeOf
outra coisa porquewritable: false
.Mixins (usando # Object.assign) - Anakin Skywalker
Você pode sentir para onde isso está indo ...?
Darth Vader obtém os métodos de
Robot
:Juntamente com outras coisas estranhas:
Bem, se Darth Vader é homem ou máquina é realmente subjetivo:
Extra - sintaxe um pouco mais curta com # Object.assign
Com toda a probabilidade, esse padrão reduz sua sintaxe. Porém, o ES6 # Object.assign pode reduzir um pouco mais (para o polyfill usar em navegadores mais antigos, consulte MDN no ES6 ).
fonte
Object.assign(Robot, {a:1}
uma boa alternativa para o seuextend()
método? 2) Como substituir ogreet()
método para que ele retorne o mesmo texto, mas com "uma substituição de saudação" anexada?#Object.assign
parece uma boa alternativa. Mas o suporte ao navegador é menor. 2) Você usará a__proto__
propriedade do objeto para acessar a função greet do seu protótipo. então você chama a função protótipo greet com o escopo do receptor transmitido. Nesse caso, a função era um log do console; portanto, não é possível "anexar". Mas com este exemplo, acho que você entendeu.skywalker.greet = function() { this.__proto__.greet.call(this); console.log('a greet override'); }
Se você ainda não descobriu uma maneira, use a propriedade associativa dos objetos JavaScript para adicionar uma função de extensão à,
Object.prototype
como mostrado abaixo.Você pode usar esta função como mostrado abaixo.
fonte
Abordagem diferente: Object.create
Por resposta da @osahyoun, considero o seguinte como uma maneira melhor e eficiente de 'herdar' do objeto de protótipo de Person:
Crie novas instâncias:
Agora, usando Object.create :
Verifique também a documentação do MDN .
fonte
name
parâmetro para o construtor pai, como este: jsfiddle.net/3brm0a7a/3 (diferença está na linha # 8)No ES6 , você pode usar o operador spread como
Para obter mais informações, consulte o link MDN -Spread Syntax
Resposta antiga:
No ES6 , existe
Object.assign
para copiar valores de propriedades. Use{}
como primeiro parâmetro se não desejar modificar o objeto de destino (o primeiro parâmetro passou).Para mais detalhes, consulte o link MDN - Object.assign ()
Caso você precise de um Polyfill para ES5 , o link também o oferece. :)
fonte
E outro ano depois, posso dizer que há outra resposta legal.
Se você não gosta da maneira como a prototipagem funciona para se estender a objetos / classes, veja o seguinte: https://github.com/haroldiedema/joii
Exemplo rápido de código de possibilidades (e muito mais):
fonte
Pessoas que ainda lutam pela abordagem simples e melhor, você pode usar
Spread Syntax
para estender o objeto.Nota: Lembre - se de que a propriedade que estiver mais à direita terá prioridade. Neste exemplo,
person2
está do lado direito, entãonewObj
terá o nome Robo .fonte
Você pode considerar usar a biblioteca auxiliar, como underscore.js , que possui sua própria implementação
extend()
.E também é uma boa maneira de aprender olhando para o código fonte. A página de código-fonte anotada é bastante útil.
fonte
_.extend()
obras faz sua funcionalidade bastante clara: lostechies.com/chrismissal/2012/10/05/...O Mozilla 'anuncia' o objeto que se estende do ECMAScript 6.0:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/extends
NOTA: Essa é uma tecnologia experimental, parte da proposta do ECMAScript 6 (Harmony).
Esta tecnologia está disponível no Gecko (Google Chrome / Firefox) - compilações noturnas de 03/2015.
fonte
Na maioria dos projetos, há alguma implementação de extensão de objeto: sublinhado, jquery, lodash: extensão .
Também existe uma implementação javascript pura, que faz parte do ECMAscript 6: Object.assign : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
fonte
Então:
Atualização 01/2017:
Ignore minha resposta de 2015, já que o Javascript agora suporta
extends
palavras-chave desde ES6 (Ecmasctipt6)- ES6:
- ES7:
fonte
new ParentClass()
antes de substituir o construtor, você já executou o construtor pai. Eu não acho que isso é o comportamento correto se você me perguntar ...Resumo:
Javascript usa um mecanismo que é chamado de herança prototípica . A herança prototípica é usada ao procurar uma propriedade em um objeto. Quando estamos estendendo propriedades em javascript, estamos herdando essas propriedades de um objeto real. Funciona da seguinte maneira:
myObj.foo
oumyObj['foo']
), o mecanismo JS primeiro procurará essa propriedade no próprio objetoQuando queremos estender a partir de um objeto em javascript, podemos simplesmente vincular esse objeto na cadeia de protótipos. Existem várias maneiras de conseguir isso, descreverei 2 métodos comumente usados.
Exemplos:
1
Object.create()
Object.create()
é uma função que aceita um objeto como argumento e cria um novo objeto. O objeto que foi passado como argumento será o protótipo do objeto recém-criado. Por exemplo:2. Definindo explicitamente a propriedade prototype
Ao criar objetos usando funções de construtor, podemos definir propriedades de adição à sua propriedade de objeto de protótipo. Os objetos criados formam uma função construtora ao usar a
new
palavra - chave, com seu protótipo definido para o protótipo da função construtora. Por exemplo:fonte
Você pode simplesmente fazer isso usando:
Em seguida, use-o como:
Isso também resulta em:
fonte
POR FAVOR, ADICIONE RAZÃO PARA DOWNVOTE
Não há necessidade de usar nenhuma biblioteca externa para estender
No JavaScript, tudo é um objeto (exceto os três tipos de dados primitivos, e mesmo eles são agrupados automaticamente com os objetos quando necessário). Além disso, todos os objetos são mutáveis.
graças a ross harmes, dustin diaz
fonte
Isso fará com que estender suas propriedades crie um novo objeto com os protótipos de parâmetro de objeto sem alterar o objeto passado.
Mas se você deseja estender seu Objeto sem modificá-lo, pode adicionar extendProperty ao seu objeto.
fonte
A criação de protótipos é uma maneira agradável, mas o protótipo às vezes é bastante perigoso e pode levar a erros. Eu prefiro encapsular isso em um objeto base, como o Ember.js faz com o Ember.Object.extend e o Ember.Object.reopen. Isso é muito mais seguro de usar.
Eu criei uma essência com como você configuraria algo semelhante ao que o Ember.Object usa.
Aqui está o link: https://gist.github.com/WebCloud/cbfe2d848c80d4b9e9bd
fonte
Prototyping is a nice way, but prototype is quite dangerous sometimes and can lead to bugs.
O que você quer dizer com isso? Usar a cadeia de protótipos em JavaScript pode levar a erros? É como dizer que o uso de classes em Java pode levar a erros e não faz absolutamente nenhum sentido.Object
o protótipo, sua função poderá ter o mesmo nome que uma futura função JavaScript e fazer com que seu código exploda quando executado no futuro. Por exemplo, digamos que você adicionou umarepeat()
funçãoObject
e a chamou emString
instâncias e, em seguida, seu tempo de execução JavaScript foi atualizado para o ES6?prototype
recurso de linguagem .