Em outra pergunta , um usuário apontou que a new
palavra - chave era perigosa e propôs uma solução para a criação de objetos que não era usada new
. Eu não acreditava que isso fosse verdade, principalmente porque usei Prototype, Scriptaculous e outras excelentes bibliotecas JavaScript, e todos eles usaram a new
palavra - chave.
Apesar disso, ontem eu estava assistindo a palestra de Douglas Crockford no teatro YUI e ele disse exatamente a mesma coisa, que ele não usava mais a new
palavra - chave em seu código ( Crockford em JavaScript - Ato III: Função Final - 50:23 minutos ).
É 'ruim' usar a new
palavra - chave? Quais são as vantagens e desvantagens de usá-lo?
javascript
Pablo Fernandez
fonte
fonte
new
. Mas quando você olha para a biblioteca YUI. Você tem que usar emnew
qualquer lugar. Tais comovar myDataSource = new Y.DataSource.IO({source:"./myScript.php"});
.init
método se estiver usando aObject.create
abordagem e chamar depois. Muito mais fácil de usar, onew
que faz as duas coisas, define a cadeia de protótipos e chama algum código inicializador.new
não é perigoso. Omitirnew
é perigoso e, portanto, ruim . Mas no ES5, você pode usar o Modo Estrito , que protege você contra esse perigo e muitos outros.Respostas:
Crockford fez muito para popularizar boas técnicas de JavaScript. Sua posição opinativa sobre os principais elementos da linguagem provocou muitas discussões úteis. Dito isto, existem muitas pessoas que tomam cada proclamação de "mau" ou "prejudicial" como evangelho, recusando-se a olhar além da opinião de um homem. Às vezes pode ser um pouco frustrante.
O uso da funcionalidade fornecida pela
new
palavra-chave tem várias vantagens sobre a construção de cada objeto do zero:prototype
e usonew
para carimbar novos objetos. Além de ser mais rápido (não é necessário código para todos os métodos do protótipo), ele evita o balão de cada objeto com propriedades separadas para cada método. Em máquinas mais lentas (ou especialmente, intérpretes JS mais lentos) quando muitos objetos estão sendo criados, isso pode significar uma economia significativa de tempo e memória.E sim,
new
tem uma desvantagem crucial, habilmente descrita por outras respostas: se você esquecer de usá-lo, seu código será quebrado sem aviso. Felizmente, essa desvantagem é facilmente mitigada - basta adicionar um pouco de código à própria função:Agora você pode ter as vantagens de
new
não ter que se preocupar com problemas causados por uso indevido acidental. Você pode até adicionar uma asserção à verificação se o pensamento de código quebrado funcionar silenciosamente o incomoda. Ou, como alguns comentaram, use a verificação para introduzir uma exceção de tempo de execução:(Observe que esse fragmento é capaz de evitar codificar o nome da função do construtor, pois, diferentemente do exemplo anterior, ele não precisa instanciar o objeto - portanto, ele pode ser copiado em cada função de destino sem modificação.)
John Resig detalha essa técnica em seu post de Instanciação "Classe" Simples , além de incluir um meio de transformar esse comportamento em suas "classes" por padrão. Definitivamente vale a pena ler ... assim como seu próximo livro, Secrets of the JavaScript Ninja , que encontra ouro oculto neste e em muitos outros recursos "prejudiciais" da linguagem JavaScript (o capítulo sobre
with
é especialmente esclarecedor para aqueles que inicialmente descartaram esse recurso muito difamado como um artifício).fonte
new
ou use uma função de invólucro para lembrá-la para você. Eu suspeito que se você está no ponto onde importa, você já exaustos outras otimizações, como memoization, assim que suas chamadas de criação será localizado de qualquer maneira ...arguments.callee
para verificar se você foi chamadonew
pode não ser tão bom, poisarguments.callee
não está disponível no modo estrito. Melhor usar o nome da função.new
porque você pode esquecer de escrevê-lo em seu código é tão ridículo quanto o meu exemplo.Acabei de ler algumas partes de seu livro de Crockfords "Javascript: The Good Parts". Tenho a sensação de que ele considera tudo o que já o mordeu como prejudicial:
Sobre o switch:
Sobre ++ e -
Sobre o novo:
Há mais, mas espero que você entenda.
Minha resposta para sua pergunta: não, não é prejudicial. mas se você esquecer de usá-lo quando tiver, poderá ter alguns problemas. Se você está desenvolvendo em um bom ambiente, percebe isso.
Atualizar
Cerca de um ano após a redação dessa resposta, foi lançada a 5ª edição do ECMAScript, com suporte ao modo estrito . No modo estrito,
this
não está mais vinculado ao objeto global, mas aundefined
.fonte
Javascript sendo uma linguagem dinâmica, há um zilhão de maneiras de atrapalhar onde outro idioma o impediria.
Evitar um recurso fundamental da linguagem, como
new
na base de que você pode estragar tudo, é como remover seus sapatos novos e brilhantes antes de caminhar por um campo minado, para o caso de você ficar enlameado.Uso uma convenção em que os nomes das funções começam com uma letra minúscula e 'funções' que são realmente definições de classe começam com uma letra maiúscula. O resultado é uma pista visual bastante convincente de que a 'sintaxe' está errada: -
Além disso, bons hábitos de nomeação ajudam. Depois que todas as funções fazem as coisas e, portanto, deve haver um verbo em seu nome, enquanto as classes representam objetos e são substantivos e adjetivos sem verbo.
É interessante como a coloração da sintaxe do SO interpretou o código acima.
fonte
if (! this instanceof MyClass) return new MyClass()
), eu realmente prefiro anew
sintaxe -less. Por quê? Porque funções são mais genéricas que funções construtoras . Sairnew
facilita a mudança de uma função de construtor para uma função regular ... Ou o contrário. A adiçãonew
torna o código mais específico do que precisa. E, portanto, menos flexível. Compare com Java, onde é recomendável aceitar, emList
vez de,ArrayList
para que o chamador possa escolher a implementação.Eu sou iniciante em Javascript, então talvez eu não tenha muita experiência em fornecer um bom ponto de vista para isso. No entanto, quero compartilhar minha opinião sobre essa coisa "nova".
Eu vim do mundo C #, onde o uso da palavra-chave "novo" é tão natural que é o padrão de design da fábrica que me parece estranho.
Quando codifico pela primeira vez em Javascript, não percebo que exista a palavra-chave e o código "novos", como o padrão YUI, e não demoro muito tempo para entrar em desastre. Perco a noção do que uma linha específica deveria estar fazendo ao olhar para trás o código que escrevi. Mais caótico é que minha mente não pode realmente transitar entre os limites das instâncias de objeto quando estou "executando a seco" o código.
Então, encontrei a "nova" palavra-chave que, para mim, "separava" as coisas. Com a nova palavra-chave, ela cria coisas. Sem a nova palavra-chave, sei que não a confundirei com a criação de coisas, a menos que a função que estou invocando me dê fortes pistas disso.
Por exemplo, com
var bar=foo();
eu não tenho pistas sobre qual barra poderia ser ... É um valor de retorno ou é um objeto recém-criado? Mas comvar bar = new foo();
eu sei com certeza bar é um objeto.fonte
typeof new foo() == "object"
. É quenew
retorna uma instância defoo
e você sabe que pode chamarfoo.bar()
efoo.bang()
. No entanto, que pode ser facilmente atenuado com o uso @return do JSDoc Não que eu estou defendendo para o código processual (evitando a palavranew
)Outro argumento para o novo é o que chamo de Pooh Coding . Winnie the Pooh segue sua barriga. Eu digo: vá com o idioma que você está usando, não contra ele.
As chances são de que os mantenedores do idioma otimizarão o idioma para os idiomas que tentam incentivar. Se eles colocarem uma nova palavra-chave no idioma, provavelmente pensam que faz sentido ficar claro ao criar uma nova instância.
O código escrito seguindo as intenções do idioma aumentará em eficiência a cada versão. E o código que evitar as principais construções da linguagem sofrerá com o tempo.
EDIT: E isso vai muito além do desempenho. Não posso contar as vezes que ouvi (ou disse) "por que diabos eles fizeram isso ?" ao encontrar código de aparência estranha. Muitas vezes acontece que, no momento em que o código foi escrito, havia alguma "boa" razão para isso. Seguir o Tao do idioma é o seu melhor seguro para não ter seu código ridicularizado daqui a alguns anos.
fonte
Eu escrevi um post sobre como atenuar o problema de chamar um construtor sem a nova palavra-chave.
É principalmente didático, mas mostra como você pode criar construtores que funcionam com ou sem
new
e não requer que você adicione código padrão para testarthis
em cada construtor.http://js-bits.blogspot.com/2010/08/constructors-without-using-new.html
Aqui está a essência da técnica:
Veja como usá-lo:
fonte
arguments.callee
é incrível!surrogateConstructor
deve sersurrogateCtor
(ou vice-versa).A lógica por trás do não uso da nova palavra-chave é simples:
Ao não usá-lo, você evita a armadilha que vem com a omissão acidental. O padrão de construção usado pelo YUI é um exemplo de como você pode evitar completamente a nova palavra-chave "
Como alternativa, você poderia fazer isso:
Mas, ao fazer isso, você corre o risco de alguém esquecer de usar a nova palavra-chave, e o operador this ser todo fubar. AFAIK, não há vantagem em fazer isso (a não ser que você esteja acostumado).
No final do dia: é sobre ser defensivo. Você pode usar a nova declaração? Sim. Isso torna seu código mais perigoso? Sim.
Se você já escreveu C ++, é como definir ponteiros para NULL depois de excluí-los.
fonte
Eu acho que "novo" adiciona clareza ao código. E a clareza vale tudo. É bom saber que existem armadilhas, mas evitá-las evitando a clareza não me parece o caminho.
fonte
Caso 1:
new
não é obrigatório e deve ser evitadoCaso 2:
new
é necessário, caso contrário, você receberá um errofonte
toString()
). Em todos os outros casos, use literais. NãoString('asd')
, mas simplesmente'asd'
, e nãoNumber(12)
, mas simplesmente12
.Array
:Array(5).fill(0)
é, obviamente, mais legível do que[undefined, undefined, undefined, undefined, undefined].fill(0)
e(var arr = []).length = 5; arr.fill(0);
new
com construtores para tipos de objetos correspondentes a tipos primitivos . O literal que você está sugerindo não é equivalente àArray
chamada (try0 in …
), e o resto é um erro de sintaxe :) Caso contrário, você está correto, embora deva-se notar também queArray(5)
pode ser ambíguo se você considerar implementações não conformes (e portanto, um emuladoArray.prototype.fill(…)
).Aqui está o breve resumo que eu poderia fazer dos dois argumentos mais fortes a favor e contra o uso do
new
operador:Argumento contra
new
new
operador podem ter efeitos desastrosos se forem invocadas incorretamente como funções normais. O código de uma função nesse caso será executado no escopo em que a função é chamada, em vez de no escopo de um objeto local, como pretendido. Isso pode fazer com que variáveis e propriedades globais sejam substituídas com consequências desastrosas.function Func()
e, em seguida, chamarFunc.prototype
e adicionar itens a ele para que você possa chamarnew Func()
para construir seu objeto parece feio para alguns programadores, que preferem usar outro estilo de herança de objetos por razões arquitetônicas e estilísticas.Para saber mais sobre esse argumento, consulte o grande e conciso livro de Douglas Crockford, Javascript: The Good Parts. De fato, confira de qualquer maneira.
Argumento a favor de
new
new
operador junto com a atribuição de protótipo é rápido.Veja o post de John Resig para uma explicação simples dessa técnica e para uma explicação geralmente mais profunda do modelo de herança que ele defende.
fonte
'use strict';
modo (ou o método no seu link) # 2 Possui açúcar sinático no ES6 , no entanto, o comportamento é o mesmo de antes.Eu concordo com pez e alguns aqui.
Parece-me óbvio que "novo" é a criação auto-descritiva de objetos, onde o padrão YUI que Greg Dean descreve é completamente obscuro .
A possibilidade de alguém escrever
var bar = foo;
ouvar bar = baz();
onde o baz não é um método de criação de objetos parece muito mais perigoso.fonte
Eu acho que novo é ruim, não porque se você esquece de usá-lo por engano, pode causar problemas, mas porque estraga a cadeia de herança, tornando a linguagem mais difícil de entender.
JavaScript é orientado a objeto baseado em protótipo. Portanto, todo objeto DEVE ser criado a partir de outro objeto como esse
var newObj=Object.create(oldObj)
. Aqui oldObj é chamado de protótipo de newObj (daí "baseado em protótipo"). Isso implica que, se uma propriedade não for encontrada em newObj , ela será pesquisada em oldObj . O newObj, por padrão, será um objeto vazio, mas devido à sua cadeia de protótipos, parece ter todos os valores de oldObj .Por outro lado, se o fizer
var newObj=new oldObj()
, o protótipo de newObj é oldObj.prototype , que é desnecessariamente difícil de entender.O truque é usar
Está dentro dessa função e somente aqui o novo deve ser usado. Após isso, basta usar o método Object.create () . O método resolve o problema do protótipo.
fonte
var c = new Car()
é o mesmo que fazer #var c = Object.create(Car.prototype); Car.call(c)