style definicion caracteristicas attribute javascript

javascript - definicion - title css



¿Es la nueva palabra clave de JavaScript considerada dañina? (12)

Caso 1: el new no es necesario y debe evitarse

var str = new String(''asd''); // type: object var str = String(''asd''); // type: string var num = new Number(12); // type: object var num = Number(12); // type: number

Caso 2: se requiere new , de lo contrario obtendrá un error

new Date().getFullYear(); // correct, returns the current year, i.e. 2010 Date().getFullYear(); // invalid, returns an error

En otra question , un usuario señaló que la new palabra clave era peligrosa de usar y propuso una solución para la creación de objetos que no usaba new . No creía que eso fuera cierto, principalmente porque he usado Prototype, Scriptaculous y otras excelentes bibliotecas de JavaScript, y cada uno de ellos usó la new palabra clave.

A pesar de eso, ayer estuve viendo la charla de Douglas Crockford en el teatro YUI y dijo exactamente lo mismo, que ya no usaba la new palabra clave en su código ( Crockford en JavaScript - Acto III: Funciona lo último - 50: 23 minutos ).

¿Es "malo" usar la new palabra clave? ¿Cuáles son las ventajas y desventajas de usarlo?


Acabo de leer algunas partes de su libro de Crockford "Javascript: The Good Parts". Tengo la sensación de que él considera que todo lo que lo ha mordido es perjudicial:

Acerca de la caída del interruptor a través de:

Nunca permito que los casos de cambio pasen al siguiente caso. Una vez encontré un error en mi código causado por una caída involuntaria inmediatamente después de haber pronunciado un enérgico discurso sobre por qué la caída a veces era útil. (página 97, ISBN 978-0-596-51774-8)

Acerca de ++ y -

Se sabe que los operadores ++ (incremento) y - (decremento) contribuyen al código incorrecto al fomentar el engaño excesivo. Solo son superados por la arquitectura defectuosa al habilitar virus y otras amenazas de seguridad. (página 122)

Sobre nuevo

Si olvida incluir el nuevo prefijo cuando llama a una función de constructor, esto no estará vinculado al nuevo objeto. Lamentablemente, esto se vinculará al objeto global, por lo que, en lugar de aumentar su nuevo objeto, estará dominando las variables globales. Eso es realmente malo. No hay una advertencia de compilación, y no hay una advertencia de tiempo de ejecución. (página 49)

Hay más, pero espero que se haga una idea.

Mi respuesta a tu pregunta: No, no es perjudicial. pero si olvida usarlo cuando debería, podría tener algunos problemas. Si se está desarrollando en un buen ambiente, notará eso.

Actualizar

Aproximadamente un año después de que se escribiera esta respuesta, se lanzó la quinta edición de ECMAScript, con soporte para el modo estricto . En modo estricto, this ya no está vinculado al objeto global sino a undefined .


Aquí está el resumen más breve que pude hacer de los dos argumentos más fuertes a favor y en contra del uso del new operador:

Argumento en contra de new

  1. Las funciones diseñadas para ser instanciadas como objetos usando el new operador pueden tener efectos desastrosos si se invocan incorrectamente como funciones normales. El código de una función en tal caso se ejecutará en el ámbito donde se llama la función, en lugar de en el alcance de un objeto local como se pretende. Esto puede hacer que las variables y propiedades globales se sobrescriban con consecuencias desastrosas.
  2. Finalmente, escribir la function Func() y luego llamar a Func.prototype y agregarle cosas para que pueda llamar a la new Func() para construir su objeto parece feo para algunos programadores, quienes prefieren usar otro estilo de herencia de objetos para arquitectura y arquitectura. razones estilísticas.

Para más información sobre este argumento, echa un vistazo al excelente y conciso libro de Douglas Crockford, Javascript: The Good Parts. De hecho, échale un vistazo de todos modos.

Argumento a favor de la new

  1. Usar el new operador junto con la asignación de prototipos es rápido.
  2. Todo lo relacionado con la ejecución accidental del código de una función de constructor en el espacio de nombres global puede evitarse fácilmente si siempre incluye un poco de código en sus funciones de constructor para verificar si se están llamando correctamente y, en los casos en que no lo están. , manejando la llamada apropiadamente como se desee.

Vea la publicación de John Resig para una explicación simple de esta técnica, y para una explicación generalmente más profunda del modelo de herencia que él defiende.


Creo que "nuevo" añade claridad al código. Y la claridad lo vale todo. Es bueno saber que hay dificultades, pero evitarlas evitando la claridad no parece ser el camino para mí.


Creo que lo nuevo es malo, no porque si olvidas usarlo por error puede causar problemas, sino porque arruina la cadena de la herencia, haciendo que el lenguaje sea más difícil de entender.

JavaScript está basado en prototipos orientado a objetos. Por lo tanto, cada objeto DEBE ser creado a partir de otro objeto como var newObj=Object.create(oldObj) . Aquí oldObj se llama el prototipo de newObj (por lo tanto, "basado en prototipo"). Esto implica que si una propiedad no se encuentra en newObj, entonces se buscará en oldObj . newObj por defecto será un objeto vacío, pero debido a su cadena de prototipo parece tener todos los valores de oldObj .

Por otro lado, si haces var newObj=new oldObj() , el prototipo de newObj es oldObj.prototype , que es innecesariamente difícil de entender.

El truco es usar

Object.create=function(proto){ var F = function(){}; F.prototype = proto; var instance = new F(); return instance; };

Está dentro de esta función y solo aquí se debe usar lo nuevo. Después de esto, simplemente use el método Object.create () . El método resuelve el problema del prototipo.


Crockford ha hecho mucho para popularizar las buenas técnicas de JavaScript. Su postura opinada sobre los elementos clave del lenguaje ha provocado muchas discusiones útiles. Dicho esto, hay demasiadas personas que toman cada anuncio de "malo" o "dañino" como evangelio, negándose a mirar más allá de la opinión de un hombre. Puede ser un poco frustrante a veces.

El uso de la funcionalidad proporcionada por la new palabra clave tiene varias ventajas sobre la creación de cada objeto desde cero:

  1. Herencia prototipo . Si bien la técnica de herencia nativa de JavaScript es una forma simple y sorprendentemente efectiva de reutilizar el código, a menudo se la ve con una mezcla de desconfianza y burla por parte de aquellos acostumbrados a los lenguajes OO basados ​​en clases. Y la nueva palabra clave es el medio canónico (y solo disponible multiplataforma) de su uso.
  2. Actuación. Este es un efecto secundario de # 1: si quiero agregar 10 métodos a cada objeto que creo, podría escribir una función de creación que asigne manualmente cada método a cada nuevo objeto ... O, podría asignarlos a la prototype la función de prototype y uso new para sellar nuevos objetos. Esto no solo es más rápido (no se necesita código para todos y cada uno de los métodos en el prototipo), sino que también evita hacer volar cada objeto con propiedades separadas para cada método. En máquinas más lentas (o especialmente en intérpretes JS más lentos) cuando se crean muchos objetos, esto puede significar un ahorro significativo en tiempo y memoria.

Y sí, lo new tiene una desventaja crucial, tal como lo describen otras respuestas: si olvida usarlo, su código se romperá sin previo aviso. Afortunadamente, esa desventaja se puede mitigar fácilmente, simplemente agregue un poco de código a la función en sí:

function foo() { // if user accidentally omits the new keyword, this will // silently correct the problem... if ( !(this instanceof foo) ) return new foo(); // constructor logic follows... }

Ahora puede tener las ventajas de lo new sin tener que preocuparse por los problemas causados ​​por un mal uso accidental. Incluso podría agregar una aserción al cheque si le molesta la idea de que el código roto funcione de manera silenciosa. O, como some comentaron, use la verificación para introducir una excepción de tiempo de ejecución:

if ( !(this instanceof arguments.callee) ) throw new Error("Constructor called as a function");

(Tenga en cuenta que este fragmento de código puede evitar la codificación rígida del nombre de la función del constructor, ya que, a diferencia del ejemplo anterior, no tiene necesidad de instanciar realmente el objeto; por lo tanto, puede copiarse en cada función de destino sin modificaciones).

John Resig entra en detalles sobre esta técnica en su publicación de instanciación de "clase" simple , así como también incluye un medio para construir este comportamiento en sus "clases" de forma predeterminada. Definitivamente vale la pena leerlo ... al igual que su próximo libro, Secrets of JavaScript Ninja , que encuentra oro oculto en esta y muchas otras características "dañinas" del lenguaje JavaScript (el capítulo with es especialmente ilustrativo para aquellos de nosotros que inicialmente desestimó esta característica tan difamada como un truco).


Escribí una publicación sobre cómo mitigar el problema de llamar a un constructor sin la nueva palabra clave.
Es sobre todo didáctico, pero muestra cómo puede crear constructores que trabajen con o sin new y no requiere que agregue código repetitivo para probar this en cada constructor.

http://js-bits.blogspot.com/2010/08/constructors-without-using-new.html

Aquí está la esencia de la técnica:

/** * Wraps the passed in constructor so it works with * or without the new keyword * @param {Function} realCtor The constructor function. * Note that this is going to be wrapped * and should not be used directly */ function ctor(realCtor){ // This is going to be the actual constructor return function wrapperCtor(){ var obj; // object that will be created if (this instanceof wrapperCtor) { // Called with new obj = this; } else { // Called without new. Create an empty object of the // correct type without running that constructor surrogateCtor.prototype = wrapperCtor.prototype; obj = new surrogateCtor(); } // Call the real constructor function realCtor.apply(obj, arguments); return obj; } function surrogateCtor() {} }

Aquí está cómo usarlo:

// Create our point constructor Point = ctor(function(x,y){ this.x = x; this.y = y; }); // This is good var pt = new Point(20,30); // This is OK also var pt2 = Point(20,30);


Estoy de acuerdo con pez y algunos aquí.

Me parece obvio que "nuevo" es la creación de objetos autodescriptivos, donde el patrón YUI que Greg Dean describe está completamente oculto .

La posibilidad de que alguien pueda escribir var bar = foo; o var bar = baz(); donde baz no es un objeto crear un método parece mucho más peligroso.


Javascript es un lenguaje dinámico, hay miles de formas de desordenar donde otro idioma lo detendría.

Evitar una característica fundamental del lenguaje como new sobre la base de que podría estropearse es un poco como quitarse los zapatos nuevos y brillantes antes de caminar por un campo minado en caso de que pueda ensuciarlos.

Utilizo una convención donde los nombres de funciones comienzan con una letra minúscula y las "funciones" que en realidad son definiciones de clase comienzan con una letra mayúscula. El resultado es una pista visual bastante convincente de que la ''sintaxis'' es incorrecta:

var o = MyClass(); // this is clearly wrong.

Por encima de estos buenos hábitos de nombrar ayuda. Después de que todas las funciones hacen cosas y, por lo tanto, debería haber un verbo en su nombre, mientras que las clases representan objetos y son nombres y adjetivos sin verbo.

var o = chair() // Executing chair is daft. var o = createChair() // makes sense.

Es interesante cómo la sintaxis de los colores de SO ha interpretado el código anterior.


La razón detrás de no usar la nueva palabra clave, es simple:

Al no utilizarlo en absoluto, evita la trampa que conlleva omitirlo accidentalmente. El patrón de construcción que usa YUI, es un ejemplo de cómo puede evitar la nueva palabra clave por completo "

var foo = function () { var pub= { }; return pub; } var bar = foo();

Alternativamente, podrías hacer esto:

function foo() { } var bar = new foo();

Pero al hacerlo, corre el riesgo de que alguien se olvide de usar la nueva palabra clave y de que este operador sea todo fubar. AFAIK no hay ninguna ventaja en hacer esto (aparte de que usted está acostumbrado).

Al final del día: se trata de estar a la defensiva. ¿Se puede utilizar la nueva declaración? Sí. ¿Hace tu código más peligroso? Sí.

Si alguna vez ha escrito C ++, es similar a establecer punteros en NULL después de eliminarlos.


Otro caso nuevo es lo que yo llamo Codificación Pooh . Winnie the Pooh sigue su barriga. Yo digo que vaya con el lenguaje que está utilizando, no en contra de él.

Es probable que los mantenedores del idioma optimicen el idioma para los idiomas que intentan fomentar. Si colocan una nueva palabra clave en el idioma, probablemente piensen que tiene sentido dejar en claro al crear una nueva instancia.

El código escrito siguiendo las intenciones del idioma aumentará en eficiencia con cada versión. Y el código que evita las construcciones clave del lenguaje sufrirá con el tiempo.

EDIT: Y esto va más allá del rendimiento. No puedo contar las veces que escuché (o dije) "¿por qué demonios hicieron eso ?" Al encontrar código de aspecto extraño. A menudo resulta que en el momento en que se escribió el código había una buena razón para ello. Seguir el Tao del idioma es su mejor seguro para no ridiculizar su código en algunos años.


Soy un novato en Javascript, así que quizás no tenga mucha experiencia en proporcionar un buen punto de vista para esto. Sin embargo, quiero compartir mi opinión sobre esta "nueva" cosa.

Vengo del mundo C # donde usar la palabra clave "nuevo" es tan natural que es el patrón de diseño de fábrica que me parece extraño.

La primera vez que codifiqué en Javascript, no me doy cuenta de que hay una palabra clave y un código "nuevos" como el del patrón YUI y no me lleva mucho tiempo correr un desastre. Perdí el rastro de lo que se supone que debe hacer una línea en particular al mirar hacia atrás el código que he escrito. Más caótico es que mi mente no puede realmente transitar entre los límites de las instancias de objetos cuando estoy "ejecutando en seco" el código.

Luego, encontré la "nueva" palabra clave que, para mí, "separa" las cosas. Con la nueva palabra clave, crea cosas. Sin la nueva palabra clave, sé que no la confundiré con crear cosas a menos que la función que invoco me dé pistas sólidas de eso.

Por ejemplo, con var bar=foo(); No tengo pistas sobre qué barra podría ser ... ¿Es un valor de retorno o es un objeto creado recientemente? Pero con var bar = new foo(); Sé con seguridad que la barra es un objeto.