Recentemente, deparei com o Object.create()
método em JavaScript e estou tentando deduzir como ele é diferente de criar uma nova instância de um objeto new SomeFunction()
e quando você deseja usar um sobre o outro.
Considere o seguinte exemplo:
var test = {
val: 1,
func: function() {
return this.val;
}
};
var testA = Object.create(test);
testA.val = 2;
console.log(test.func()); // 1
console.log(testA.func()); // 2
console.log('other test');
var otherTest = function() {
this.val = 1;
this.func = function() {
return this.val;
};
};
var otherTestA = new otherTest();
var otherTestB = new otherTest();
otherTestB.val = 2;
console.log(otherTestA.val); // 1
console.log(otherTestB.val); // 2
console.log(otherTestA.func()); // 1
console.log(otherTestB.func()); // 2
Observe que o mesmo comportamento é observado nos dois casos. Parece-me que as principais diferenças entre esses dois cenários são:
- O objeto usado na
Object.create()
verdade forma o protótipo do novo objeto, enquanto que nasnew Function()
propriedades / funções declaradas não formam o protótipo. - Você não pode criar fechamentos com a
Object.create()
sintaxe como faria com a sintaxe funcional. Isso é lógico, considerando o escopo do tipo lexical (vs block) do JavaScript.
As afirmações acima estão corretas? E estou faltando alguma coisa? Quando você usaria um sobre o outro?
EDIT: link para a versão jsfiddle do exemplo de código acima: http://jsfiddle.net/rZfYL/
Respostas:
Sim,
Object.create
cria um objeto que herda diretamente do passado como seu primeiro argumento.Com as funções do construtor, o objeto recém-criado herda do protótipo do construtor, por exemplo:
No exemplo acima,
o
herda diretamente deSomeConstructor.prototype
.Há uma diferença aqui:
Object.create
você pode criar um objeto que não herda de nadaObject.create(null);
; por outro lado, se você definirSomeConstructor.prototype = null;
o objeto recém-criado, herdaráObject.prototype
.Bem, você pode criar fechamentos, por exemplo, usando o argumento de descritores de propriedades:
Observe que estou falando do
Object.create
método ECMAScript 5th Edition , não do calço de Crockford.O método está começando a ser implementado nativamente nos navegadores mais recentes, verifique esta tabela de compatibilidade .
fonte
foo;
é resolvido no ambiente lexical atual . 2) Para fornecer uma maneira fácil de implementar herança, é uma construção realmente poderosa. Na IMO, eu o usaria porque é realmente simples e leve, mas para o código de produção, ainda precisamos esperar um pouco até que o ES5 seja amplamente suportado. Sobre recursos ausentes, o fato de criar um objeto "intocada",Object.create(null);
estava faltando, é realmente útil para implementar confiável de hash-table-como objetos ...Object.create(null)
significa que você não precisa usarhasOwnProperty()
porcaria ao iterar porque ele não herda nenhum ??? Eu gosto disso - obrigado. Claro, todo mundo ainda vai fazer,hasOwnProperty
já que nem todo mundo vai usar,Object.create(null)
então não tenho certeza de que seja um benefício real ... Até agora, encontrei os outros "benefícios" deObject.create()
não ser convincente.Muito simplesmente,
new X
estáObject.create(X.prototype)
executando adicionalmente aconstructor
função. (E dando aconstructor
chance aoreturn
objeto real que deve ser o resultado da expressão em vez dethis
.)É isso aí. :)
O restante das respostas é apenas confuso, porque aparentemente ninguém mais lê a definição de
new
nenhum dos dois. ;)fonte
Aqui estão as etapas que ocorrem internamente para as duas chamadas:
(Dica: a única diferença está na etapa 3)
new Test()
:new Object()
objobj.__proto__
comoTest.prototype
return Test.call(obj) || obj; // normally obj is returned but constructors in JS can return a value
Object.create( Test.prototype )
new Object()
objobj.__proto__
comoTest.prototype
return obj;
Então, basicamente
Object.create
, não executa o construtor.fonte
new
basicamente todas as funções são duplicadas, enquantoObject.create
não.Deixe-me tentar explicar (mais no Blog ):
Car
construtorvar Car = function(){}
, é assim que as coisas são internamente: Nós temos um{prototype}
link escondido paraFunction.prototype
que não é acessível e umprototype
link paraCar.prototype
que é acessível e tem um realconstructor
deCar
. Function.prototype e Car.prototype têm links ocultos paraObject.prototype
.Quando queremos criar dois objetos equivalentes usando o
new
operador e ocreate
método, devemos fazê-lo assim:Honda = new Car();
eMaruti = Object.create(Car.prototype)
. O que está acontecendo?Honda = new Car();
- Quando você cria um objeto como este, a{prototype}
propriedade oculta é apontadaCar.prototype
. Então, aqui, o{prototype}
objeto Honda sempre seráCar.prototype
- não temos opção de alterar a{prototype}
propriedade do objeto. E se eu quiser alterar o protótipo do nosso objeto recém-criado?Maruti = Object.create(Car.prototype)
- Ao criar um objeto como esse, você tem uma opção extra para escolher a{prototype}
propriedade do seu objeto . Se você deseja Car.prototype como o{prototype}
, passe-o como um parâmetro na função Se você não quer nenhum{prototype}
para o seu objeto, em seguida, você pode passarnull
assim:Maruti = Object.create(null)
.Conclusão - Ao usar o método,
Object.create
você tem a liberdade de escolher sua{prototype}
propriedade de objeto . Emnew Car();
, você não tem essa liberdade.Maneira preferida em OO JavaScript:
Suponha que temos dois objetos
a
eb
.Agora, suponha que
a
tenha alguns métodos queb
também desejem acessar. Para isso, exigimos herança de objeto (a
deve ser o protótipob
somente se quisermos acessar esses métodos). Se verificarmos os protótipos dea
eb
depois descobriremos que eles compartilham o protótipoObject.prototype
.Problema - queremos objeto
a
como o protótipo deb
, mas aqui criamos objetob
com o protótipoObject.prototype
. Solução - introduzido o ECMAScript 5Object.create()
, para obter facilmente essa herança. Se criarmos um objetob
como este:então,
Portanto, se você estiver executando scripts orientados a objetos,
Object.create()
será muito útil para herança.fonte
a.isPrototypeOf(b);
retornará ofalse
que é certo, porque os dois objetos são diferentes e apontam para uma memória diferente. A maneira correta de fazer isso com onew
operador está aqui. - jsfiddle.net/167onunp .Este:
e
são bem parecidos. Uma diferença importante é que,
new Foo
na verdade, ele executa código de construtor, enquantoObject.create
que não executa código comoObserve que se você usar a versão de dois parâmetros
Object.create()
, poderá fazer coisas muito mais poderosas.fonte
Object.create
em sua forma mais simples como essa permite que você omita as funções construtoras do seu código enquanto tira proveito da herança do protótipo.A diferença é a chamada "herança pseudoclássica vs. prototípica". A sugestão é usar apenas um tipo no seu código, não misturando os dois.
Na herança pseudoclássica (com o operador "novo"), imagine que você primeiro defina uma pseudo-classe e depois crie objetos a partir dessa classe. Por exemplo, defina uma pseudo classe "Pessoa" e crie "Alice" e "Bob" a partir de "Pessoa".
Na herança prototípica (usando Object.create), você cria diretamente uma pessoa específica "Alice" e, em seguida, cria outra pessoa "Bob" usando "Alice" como protótipo. Não há "classe" aqui; todos são objetos.
Internamente, o JavaScript usa "herança prototípica"; o caminho "pseudoclássico" é apenas um pouco de açúcar.
Veja este link para uma comparação das duas maneiras.
fonte
Resumo:
1) com a
new
palavra-chave, há duas coisas a serem observadas;a) a função é usada como construtor
b) o
function.prototype
objeto é passado para a__proto__
propriedade ... ou onde__proto__
não é suportado, é o segundo lugar em que o novo objeto procura encontrar propriedades2) com
Object.create(obj.prototype)
você construindo um objeto (obj.prototype
) e passando-o para o objeto pretendido .. com a diferença que agora o novo objeto__proto__
também está apontando para obj.prototype (consulte xj9 para isso)fonte
Variantes de criação de objeto.
Variante 1 : ' new Object () ' -> Construtor de objetos sem argumentos.
Variante 2 : ' new Object (person) ' -> Construtor de objetos com argumento.
Variante 3.1 : ' Object.create (person) '. Use Object.create com o objeto simples 'person'. 'Object.create (person)' criará (e retornará) um novo objeto vazio e adicionará a propriedade '__proto__' ao mesmo novo objeto vazio. Esta propriedade '__proto__' apontará para o objeto 'pessoa'.
Variante 3.2 : ' Object.create (Object.prototype) '. Use Object.create com o objeto interno -> 'Object.prototype'. 'Object.create (Object.prototype)' criará (e retornará) um novo objeto vazio e adicionará a propriedade '__proto__' ao mesmo novo objeto vazio. Esta propriedade '__proto__' apontará para o objeto 'Object.prototype'.
Variante 4 : ' new SomeFunction () '
fonte
Internamente,
Object.create
faz isso:A sintaxe apenas tira a ilusão de que o JavaScript usa a herança clássica.
fonte
Object.create
método ECMAScript 5 faz muito mais do que isso, você pode definir propriedades por descritores de propriedades e criar um objeto que não herda de nada (Object.create(null);
); esse tipo de calço deve ser evitado porque você não pode emular comportamento no ES3. Mais informaçõesObject.create
.De acordo com esta resposta e com este vídeo, a
new
palavra-chave faz o seguinte:Cria um novo objeto.
Vincula um novo objeto à função construtora (
prototype
).Faz
this
ponto variável para o novo objeto.Executa a função construtora usando o novo objeto e a execução implícita
return this
;Atribui o nome da função do construtor à propriedade do novo objeto
constructor
.Object.create
executa apenas1st
e2nd
etapas !!!fonte