Tampoco sabré esto, ir a casa y a la granja.
La copia del código es la siguiente:
Eliminar thisisObject [clave]
o
eliminar thisisobject.key
Por cierto, hablemos sobre el uso de Delete
Hace unas semanas, tuve la oportunidad de leer el libro de JavaScript orientado a objetos de Stoyan Stefanov. Este libro está altamente calificado en Amazon (12 reseñas, 5 estrellas), por lo que tenía curiosidad por ver si era un libro tan recomendado, así que comencé a leer el capítulo de funciones. Realmente aprecio la forma en que este libro explica las cosas, y los ejemplos están organizados de una manera muy hermosa y gradual, y parece que incluso los principiantes pueden dominar fácilmente este conocimiento. Sin embargo, casi de inmediato, descubrí un malentendido interesante durante todo el capítulo, eliminando las funciones funcionales. También hay otros errores (como la diferencia entre las declaraciones de funciones y las expresiones de funciones), pero no los discutiremos en este momento.
El libro afirma:
"La función se trata como una variable normal: se puede copiar en diferentes variables, o incluso eliminarse". Se adjunta un ejemplo a esta explicación:
La copia del código es la siguiente:
var sum = function (a, b) {return a + b;}
var add = sum;
Eliminar suma
verdadero
typeOf suma;
"indefinido"
Ignorar algunos semicolones faltantes, ¿puedes ver dónde están los errores en estos códigos? Obviamente, el error es que la operación de eliminar la variable de suma no tendrá éxito. La expresión de eliminación no debe devolver verdadera, y la suma de typeOf no debe devolver "indefinida". Todo esto se debe a que es imposible eliminar variables en JavaScript. Al menos, es imposible en esta forma de declaración.
Entonces, ¿qué pasó exactamente en este ejemplo? ¿Es un error? ¿O un uso especial? Probablemente no. Este código es en realidad la salida real en la consola Firebug, y Stoyan debe haberlo usado como una herramienta para pruebas rápidas. Es casi como si Firebug siga otras reglas de eliminación. ¡Es Firebug lo que hizo que Stoyan se extraviera! Entonces, ¿qué pasó exactamente aquí?
Antes de responder a esta pregunta, primero debemos entender cómo funciona el operador Eliminar en JavaScript: ¿Qué se puede eliminar exactamente y qué no se puede eliminar? Hoy, intentaré explicar esto en detalle. Miramos el comportamiento "extraño" de Firebug y nos daremos cuenta de que no es tan extraño. Profundizaremos en lo que está oculto detrás de escena donde las variables, las funciones, asignarán valores a los atributos y los eliminaron. Veremos la compatibilidad del navegador y algunos de los errores más notorios. También discutiremos el patrón estricto de ES5 y cómo cambia el comportamiento de los operadores Eliminar.
Voy a intercambiar JavaScript y Ecmascript, lo cual significa Ecmascript (a menos que sea obvio que la implementación de JavaScript de Mozilla)
Como se esperaba, en Internet, las explicaciones de Delete son bastante escasas. El artículo del MDC es probablemente el mejor recurso para comprender, pero, desafortunadamente, carece de algunos detalles interesantes del tema. Curiosamente, una de las cosas olvidadas es la razón de la extraña manifestación de Firebug. Y la referencia de MSDN es casi inútil en estos aspectos.
Teoría
Entonces, ¿por qué podemos eliminar las propiedades de un objeto:
La copia del código es la siguiente:
var o = {x: 1};
eliminar buey; // verdadero
buey; // indefinido
Pero el objeto declarado así no se puede eliminar:
La copia del código es la siguiente:
var x = 1;
eliminar x; // FALSO
incógnita; // 1
O la función:
La copia del código es la siguiente:
función x () {}
eliminar x; // FALSO
typeof x; // "función"
Nota: Cuando una propiedad no se puede eliminar, el operador Eliminar solo devolverá falso.
Para comprender esto, primero necesitamos dominar estos conceptos sobre instancias variables y propiedades de atributos: desafortunadamente, estos conceptos rara vez se mencionan en los libros de JavaScript. Intentaré revisar brevemente estos conceptos en los próximos párrafos. ¡Estos conceptos son difíciles de entender! Si no le importa "por qué estas cosas funcionan de esta manera", omita este capítulo.
Tipo de código:
En ECMAScript, hay 3 tipos diferentes de código ejecutable: código global, código de función y código de evaluación. Estos tipos se explican más o menos en términos de nombre, aquí hay una breve descripción:
Cuando un código fuente se considera un programa, se ejecutará en un entorno global y se considera un código global. En un entorno de navegador, el contenido de los elementos de script generalmente se interpreta como programas y, por lo tanto, se ejecutan como código global.
Cualquier código que se ejecute directamente en una función obviamente se considera el código de función. En un navegador, el contenido de las propiedades del evento (como <p onClick = "...">) generalmente se interpreta como código de función.
Finalmente, el texto del código aplicado a la función Eval de EVEV se interpreta como código EVALO. Pronto descubriremos por qué este tipo es especial.
Contexto de ejecución:
Cuando se ejecuta el código ECMAScript, generalmente ocurre en un contexto de ejecución específico. El contexto de ejecución es un concepto de entidad algo abstracto, que puede ayudar a comprender cómo funcionan el alcance y las instancias variables. Para cada uno de los tres códigos ejecutables, hay un contexto de ejecución correspondiente a él. Cuando se ejecuta una función, decimos que "el control del programa ingresa al contexto de ejecución del código de función"; Cuando se ejecuta un código global, el control del programa ingresa al contexto de ejecución del código global, etc.
Como puede ver, el contexto de ejecución puede formar lógicamente una pila. Primero, puede haber una pieza de código global y su propio contexto de ejecución, y luego este código puede llamar a una función con su contexto de ejecución (de función). Esta función puede llamar a otra función, etc. Incluso si la función se llama recursivamente, se ingresará en un nuevo contexto de ejecución cada vez que se llame.
Objeto activo (objeto de activación) / objeto variable:
Cada contexto de ejecución tiene un llamado objeto variable asociado con él. Similar al contexto de ejecución, un objeto variable es una entidad abstracta, un mecanismo utilizado para describir instancias variables. Curiosamente, las variables y las funciones declaradas en el código fuente generalmente se agregan a este objeto variable como propiedades.
Cuando el control del programa ingresa al contexto de ejecución del código global, se utiliza un objeto global como un objeto variable. Esto es exactamente por qué las variables de función declaradas globales se convierten en propiedades del objeto global.
La copia del código es la siguiente:
/ * Recuerda que `esto` se refiere al objeto global cuando está en el alcance global */
var global_object = this;
var foo = 1;
Global_object.foo; // 1
foo === global_object.foo; // verdadero
Barra de funciones () {}
typeof global_object.bar; // "función"
Global_object.bar === bar; // verdadero
Ok, entonces las variables globales se convertirán en propiedades de los objetos globales, pero ¿qué sucede con las variables locales (las definidas en el código de función)? De hecho, se comportan de manera muy similar: se convertirán en propiedades de objetos variables (objetos variables). La única diferencia es que cuando en el código de función, un objeto variable no es un objeto global, sino un llamado objeto de activación. El objeto activo se crea cada vez que ingresa el contexto de ejecución del código de función.
No solo las variables y funciones declaradas en el código de función se convertirán en propiedades del objeto activo; Esto también ocurrirá en cada parámetro de función (el nombre correspondiente al parámetro formal correspondiente) y un objeto de argumentos especiales (el nombre de los argumentos). Tenga en cuenta que el objeto activo es un mecanismo de descripción interna y no se puede acceder en el código de programa.
La copia del código es la siguiente:
(función (foo) {
barra var = 2;
función baz () {}
/*
En términos abstractos,
El objeto especial de `argumentos` se convierte en una propiedad de contener el objeto de activación de la función:
Activación_object.arguments; // Objeto de argumentos
... así como argumento `foo`:
Activación_object.foo; // 1
... así como variable `bar`:
Activation_object.bar; // 2
... así como función declarada localmente:
typeof activation_object.baz; // "función"
*/
}) (1);
Finalmente, las variables declaradas en el código eval se convierten en propiedades de objetos variables en el contexto de la persona que llama. El código de evaluación simplemente usa objetos variables en el contexto de ejecución del código que lo llama.
La copia del código es la siguiente:
var global_object = this;
/* `foo` se crea como una propiedad del objeto variable de contexto llamado,
que en este caso es un objeto global */
eval ('var foo = 1;');
Global_object.foo; // 1
(función(){
/* `Bar` se crea como una propiedad del objeto variable de contexto llamado,
que en este caso es un objeto de activación para contener la función */
eval ('var bar = 1;');
/*
En términos abstractos,
Activation_object.bar; // 1
*/
}) ();
Atributos de propiedad
Casi estamos aquí. Ahora que somos conscientes de lo que está sucediendo con variables (se convierten en propiedades), el único concepto restante que debe entenderse son los atributos de la propiedad. Cada atributo puede tener 0 o más propiedades, que se seleccionan de los siguientes conjuntos: Readonly, Dentenum, DontDelete e Interno. Puede pensar en ellos como banderas, una característica que puede existir o no en propiedades. Para nuestra discusión de hoy, solo estamos interesados en DontDelete.
Cuando las variables y las funciones declaradas se convierten en atributos de objetos variables (o objetos activos del código de función, o objetos globales del código global), estos atributos se crean con el atributo de atributo DonTDelete. Sin embargo, cualquier atributo explícito (o implícito) no se incluirá con el atributo DontDelete. Es por eso que podemos eliminar algunos atributos pero no podemos eliminar otros.
La copia del código es la siguiente:
var global_object = this;
/* `foo` es una propiedad de un objeto global.
Se crea mediante declaración de variable y, por lo tanto, no se atribuye DonTDelete.
Por eso no se puede eliminar. */
var foo = 1;
eliminar foo; // FALSO
typeOf foo; // "número"
/* `Bar` es una propiedad de un objeto global.
Se crea mediante la declaración de funciones y, por lo tanto, el atributo no Delet.
Es por eso que tampoco se puede eliminar. */
Barra de funciones () {}
Eliminar barra; // FALSO
TypyOf Bar; // "función"
/* `Baz` es también una propiedad de un objeto global.
Sin embargo, se crea a través de la asignación de propiedades y, por lo tanto, no tiene atributo DontDelete.
Por eso se puede eliminar. */
Global_object.baz = 'bla';
eliminar global_object.baz; // verdadero
typeof global_object.baz; // "indefinido"
Objetos incorporados y no delete
Por lo tanto, esto es todo en esto (DontDelete): una propiedad especial de la propiedad que controla si esta propiedad se puede eliminar. Tenga en cuenta que se especifican algunos objetos incorporados para contener DontDelete, por lo que no se pueden eliminar. Por ejemplo, una variable de argumento especial (o, como sabemos ahora, la propiedad de un objeto activo) no tiene Delete. La propiedad de longitud de una instancia de función también tiene una propiedad DontDelete.
La copia del código es la siguiente:
(función(){
/ * No se puede eliminar `argumentos`, ya que tiene no delete */
eliminar argumentos; // FALSO
TypingOf argumentos; // "objeto"
/* No se puede eliminar la `longitud" de la función; también tiene no delete */
función f () {}
eliminar f.length; // FALSO
typeOf f.length; // "número"
}) ();
El atributo correspondiente al parámetro de función también tiene la característica DontDelete desde su establecimiento, por lo que no podemos eliminarlo.
La copia del código es la siguiente:
(función (foo, bar) {
eliminar foo; // FALSO
foo; // 1
Eliminar barra; // FALSO
bar; // 'bla'
}) (1, 'bla');
Asignación no declarada:
También puede recordar que una tarea no declarada crea una propiedad en el objeto global a menos que la propiedad se haya encontrado en otra parte de esta cadena de alcance ante el objeto global. Y ahora sabemos la diferencia entre la asignación de la propiedad y la declaración de variable: la segunda establece la propiedad de DontDelete, pero la primera no. Debemos tener claro por qué una tarea no declarada crea una propiedad eliminable.
La copia del código es la siguiente:
var global_object = this;
/* Crear propiedad global a través de una declaración variable; La propiedad tiene DonDelete */
var foo = 1;
/* Crear propiedad global a través de la asignación no declarada; la propiedad no tiene dontdelete */
barra = 2;
eliminar foo; // FALSO
typeOf foo; // "número"
Eliminar barra; // verdadero
TypyOf Bar; // "indefinido"
Tenga en cuenta: las propiedades se determinan cuando se crea el atributo, y las tareas posteriores no modifican las propiedades de los atributos existentes. Es muy importante comprender esta diferencia.
La copia del código es la siguiente:
/ * `foo` se crea como una propiedad con DontDelete */
función foo () {}
/* Las tareas posteriores no modifican los atributos. ¡DondDelete sigue ahí! */
foo = 1;
eliminar foo; // FALSO
typeOf foo; // "número"
/* Pero asignar a una propiedad que no existe,
crea esa propiedad con atributos vacíos (y así sin dontdelete) */
this.Bar = 1;
Eliminar barra; // verdadero
TypyOf Bar; // "indefinido"
Firebug Confusión:
¿Qué pasa en Firebug? ¿Por qué se pueden eliminar las variables declaradas en la consola? ¿No es esto contrario a lo que hemos aprendido antes? Bueno, como dije antes, el código de evaluación tiene un rendimiento especial al enfrentar declaraciones variables. Las variables declaradas en Eval en realidad se crean como atributos sin el atributo DonTDelete.
La copia del código es la siguiente:
eval ('var foo = 1;');
foo; // 1
eliminar foo; // verdadero
typeOf foo; // "indefinido"
Del mismo modo, de manera similar, cuando se llama en el código de función:
La copia del código es la siguiente:
(función(){
eval ('var foo = 1;');
foo; // 1
eliminar foo; // verdadero
typeOf foo; // "indefinido"
}) ();
Esta es la base del comportamiento anormal de Firebug. Todo el texto de la consola se analizará y ejecutará como código de evaluación, en lugar del código global o de función. Obviamente, todas las variables declaradas aquí eventualmente se convertirán en propiedades sin el atributo de DontDelete, por lo que todas pueden eliminarse fácilmente. Necesitamos comprender la diferencia entre el código global y la consola Firebug.
Eliminar variables a través de eval:
Este interesante comportamiento de evaluación, junto con otro aspecto de ECMAScript, técnicamente puede permitirnos eliminar las propiedades de "no eliminable". Una cosa sobre las declaraciones de funciones es que pueden anular las variables con el mismo nombre en el mismo contexto de ejecución.
La copia del código es la siguiente:
función x () {}
var x;
typeof x; // "función"
Observe cómo las declaraciones de función obtienen prioridad y sobrescriben variables con el mismo nombre (o, en otras palabras, las mismas propiedades en el objeto variable). Esto se debe a que las declaraciones de funciones se instancian después de la declaración variable y se les permite sobrescribirlas (declaraciones variables). Las declaraciones de funciones no solo reemplazan el valor de una propiedad, sino que también reemplazan las propiedades de esa propiedad. Si declaramos una función a través de Eval, esa función debe reemplazar las propiedades de la propiedad original (reemplazada) con sus propias propiedades. Y, dado que las variables declaradas a través de las propiedades de Eval Create sin el atributo DonTDelete, instanciando esta nueva función en realidad eliminará el atributo DontDelete existente de la propiedad, de modo que se pueda eliminar una propiedad (y, obviamente, apunta su valor a la función recién creada).
La copia del código es la siguiente:
var x = 1;
/ * No puedo eliminar, `x` tiene no delete */
eliminar x; // FALSO
typeof x; // "número"
eval ('function x () {}');
/ * `X` La propiedad ahora las referencias funcionan, y no deberían tener DontDelete */
typeof x; // "función"
eliminar x; // debería ser 'verdadero'
typeof x; // debe ser "indefinido"
Desafortunadamente, este "engaño" no funciona en ninguna implementación en la actualidad. Tal vez me estoy perdiendo algo aquí, o tal vez el comportamiento es demasiado oscuro que el implementador no lo nota.
Compatibilidad del navegador:
Es útil en teoría comprender cómo funcionan las cosas, pero la práctica es lo más importante. ¿El navegador sigue los estándares cuando se trata de crear/eliminar variables/propiedades? La respuesta es: en la mayoría de los casos, sí.
Escribí un conjunto de prueba simple para probar la compatibilidad del navegador con los operadores de eliminación, incluidas las pruebas en código global, código de función y código de evaluación. El conjunto de pruebas verifica si el valor de retorno y los valores de atributo del operador Eliminar (como deberían comportarse) realmente se eliminan. El valor de retorno de Delete no es tan importante como su resultado real. Si Delete devuelve verdadero en lugar de falso, esto no es importante, y lo importante es que los atributos con el atributo DonTDelete no se eliminan, y viceversa.
Los navegadores modernos son generalmente bastante compatibles. Además de las características de evaluación que mencioné anteriormente, los siguientes navegadores han pasado todos los conjuntos de pruebas: Opera 7.54+, Firefox 1.0+, Safari 3.1.2+, Chrome 4+.
Safari 2.x y 3.0.4 tienen problemas al eliminar los parámetros de la función; Estas propiedades parecen ser creadas sin DontDelete, por lo que se pueden eliminar. Safari 2.x tiene más problemas: eliminar variables no referenciadas (como Delete 1) arrojará excepciones; Las declaraciones de funciones crean propiedades eliminables (pero, extrañamente, las declaraciones variables no lo hacen); Las declaraciones variables en Eval se volverán no sueltas (pero las declaraciones de funciones son eliminables).
Similar a Safari, Konqueror (3.5, no 4.3) lanza una excepción al eliminar un tipo no referencias (como: Eliminar 1), y incorrectamente hace que las variables de función se eliminen.
Nota del traductor:
Probé las últimas versiones de Chrome, Firefox e IE, y básicamente conservé la situación en la que todos los demás pases, excepto 23 y 24, fallarán. Al mismo tiempo, probé UC y algunos navegadores móviles. Excepto por el navegador incorporado del Nokia E72, que también tiene fallas 15 y 16, los otros navegadores incorporados son principalmente los mismos que los navegadores de escritorio. Pero vale la pena mencionar que el navegador incorporado de BlackBerry Curve 8310/8900 puede pasar 23, lo que me sorprendió.
Gecko Donkdelete Bug:
Gecko 1.8.x Browser - Firefox 2.x, Camino 1.x, Seamonkey 1.x, etc. - muestra un error muy interesante, la asignación explícita de una propiedad eliminará su propiedad DontDelete, incluso si esta propiedad se crea mediante declaraciones variables o declaraciones de funciones.
La copia del código es la siguiente:
función foo () {}
eliminar foo; // falso (como se esperaba)
typeOf foo; // "función" (como se esperaba)
/ * Ahora asigne a una propiedad explícitamente */
this.foo = 1; // borra erróneamente el atributo no delete
eliminar foo; // verdadero
typeOf foo; // "indefinido"
/ * Tenga en cuenta que esto no sucede al asignar propiedades implícitamente */
Barra de funciones () {}
barra = 1;
Eliminar barra; // FALSO
TypyOf Bar; // "número" (aunque la asignación reemplazó la propiedad)
Sorprendentemente, Internet Explorer 5.5 - 8 pasó el conjunto de pruebas completas, excepto que eliminar los tipos no referenciados (como Delete 1) lanzará excepciones (al igual que el antiguo Safari). Sin embargo, hay errores más graves en IE, lo cual no es tan obvio. Estos errores están relacionados con el objeto global.
Es decir, errores:
¿Todo este capítulo habla de Internet Explorer Bugs? ¡Guau! ¡Es increíble!
En IE (al menos IE 6-8), la siguiente expresión arroja una excepción (cuando se ejecuta en el código global):
this.x = 1;
eliminar x; // typeError: el objeto no admite esta acción
Este también lo hará, pero lanzará diferentes excepciones, lo que hace que las cosas sean aún más interesantes:
var x = 1;
eliminar esto.x; // typeError: no puede eliminar 'this.x'
Esto parece en IE, las declaraciones variables en el código global no crean atributos en el objeto global. Creación de atributos por asignación (this.x = 1) y luego eliminarlo de eliminar x luego arroja un error. Crear atributos por declaración (var x = 1) y eliminarlo luego arroja otro error.
Pero eso no es todo. La creación de propiedades mediante tareas explícitas en realidad siempre causará excepciones de lanzamiento cuando se elimine. No solo hay errores aquí, sino que las propiedades creadas parecen tener el atributo DonTdelete, que por supuesto no debería ser.
this.x = 1;
eliminar esto.x; // typeError: el objeto no admite esta acción
typeof x; // "número" (todavía existe, ¡no se eliminó como debería haber sido!)
eliminar x; // typeError: el objeto no admite esta acción
typeof x; // "número" (no fue eliminado de nuevo)
Ahora, pensaríamos que bajo IE, las tareas no declaradas (las propiedades deben crearse en objetos globales) crean propiedades eliminables.
x = 1;
eliminar x; // verdadero
typeof x; // "indefinido"
Sin embargo, si elimina esta propiedad a través de esta referencia en el código global (eliminar este.x), aparecerá un error similar.
x = 1;
eliminar esto.x; // typeError: no puede eliminar 'this.x'
Si queremos resumir este comportamiento, parece que el uso de eliminar esto.x para eliminar las variables del código global nunca tendrá éxito. Cuando la propiedad en la pregunta se crea mediante asignación explícita (this.x = 1), Delete lanza un error; Cuando la propiedad es creada por una asignación no declarada (x = 1) o por una declaración (var x = 1), eliminar otro error.
Eliminar x, por otro lado, se debe lanzar un error solo cuando la propiedad se crea mediante asignación explícita: this.x = 1. Si se crea una propiedad por declaración (var x = 1), la operación de eliminación nunca ocurre y la operación de eliminación devuelve correctamente falso. Si se crea una propiedad por asignación no declarada (x = 1), la operación Eliminar funciona como se esperaba.
Pensé en este tema nuevamente en septiembre. Garrett Smith sugirió que bajo IE,
"El objeto variable global se implementa como un objeto JScript, y el objeto global es implementado por el host".
Garrett usó la entrada del blog de Eric Lippert como referencia.
Podemos confirmar más o menos esta teoría implementando algunas pruebas. Tenga en cuenta que esto y la ventana parecen apuntar al mismo objeto (si podemos confiar en el operador ===), pero el objeto variable (el objeto donde se encuentra la declaración de función) es diferente de lo que esto apunta.
La copia del código es la siguiente:
/ * en código global */
function getBase () {return esto; }
getBase () === this.getBase (); // FALSO
this.getBase () === this.getBase (); // verdadero
Window.getBase () === this.getBase (); // verdadero
Window.getBase () === getBase (); // FALSO
malentendido:
La belleza de comprender por qué las cosas funcionan de esa manera no se debe subestimar. He visto algunos malentendidos sobre el operador Eliminar en Internet. Por ejemplo, la respuesta en StackOverflow (con una calificación sorprendentemente alta), explica con confianza
"Cuando el operando de destino no es una propiedad de objeto, Delete debe estar operativo".
Ahora que hemos entendido el núcleo del comportamiento de operación Eliminar, el error en esta respuesta se vuelve obvio. Eliminar no distingue entre variables y atributos (de hecho, para eliminar, son tipos de referencia) y, de hecho, solo se preocupan por los atributos de no delete (y si los atributos mismos existen).
También es muy interesante ver varios malentendidos refutándose entre sí. En un mismo tema, una persona sugirió primero que solo eliminar las variables (esto no funcionará a menos que se declare en Eval), mientras que otra persona proporcionó una corrección de errores a cómo se usa Delete para eliminar las variables en el código global, pero no en el código de función.
Tenga mucho cuidado con la explicación de JavaScript en Internet. El método ideal es comprender siempre la esencia del problema. ;)
Eliminar y el objeto de host (objeto host):
El algoritmo Delete es más o menos así:
Devolver verdadero si el operando no es un tipo de referencia
Si el objeto no tiene un atributo directo de este nombre, return True (como sabemos, el objeto puede ser un objeto activo o un objeto global)
Si la propiedad existe pero tiene el atributo DontDelete, devuelva falso
En otros casos, elimine el atributo y devuelve verdadero
Sin embargo, el comportamiento del operador de eliminación en el objeto host es impredecible. Y este comportamiento no es realmente incorrecto: (por el estándar), el objeto host puede implementar cualquier comportamiento para varios operadores como el método Read (interno [[get]]), escribir (interno [put]] método) y eliminar (interno [eliminar]] método). Esta gracia para el comportamiento personalizado [[eliminar]] es lo que hace que el objeto del host sea tan confuso.
Hemos visto algunas peculiaridades IE, donde la eliminación de objetos específicos (que obviamente se implementan como objetos de host) arrojarán errores. Algunas versiones de Firefox lanzarán al eliminar la ventana. Cuando los operandos son objetos de host, no puede confiar en el valor de retorno de Delete. Veamos qué sucede en Firefox:
La copia del código es la siguiente:
/ * "Alerta" es una propiedad directa de `Window` (si creyeríamos 'HaswnProperty`) */
Window.HasownProperty ('alerta'); // verdadero
Eliminar ventana.alert; // verdadero
typeOf Window.alert; // "función"
Eliminar Window.alert Devuelve verdadero, incluso si no hay razón para que esta propiedad cause tal resultado. Se resolverá a una referencia (por lo que no devolverá verdadero en el primer paso). Esta es una propiedad directa de un objeto de ventana (por lo que no devolverá verdadero en el segundo paso). Entonces, el único caso en el que Delete puede devolver verdadero es llegar al cuarto paso y eliminar esa propiedad. Sin embargo, esta propiedad nunca se elimina.
La moraleja de esta historia es: nunca confíes en el objeto anfitrión.
ES5 Modo estricto:
Entonces, ¿qué nos trae Strict Mode ECMAScript5? Presenta pocas limitaciones. Cuando la expresión del operador de eliminación es una referencia directa a una variable, un parámetro de función o un identificador de función, se lanzará un error de sintaxis. Además, si la propiedad tiene una propiedad interna [[configurable]] == falso, se lanzará un error de tipo.
La copia del código es la siguiente:
(función (foo) {
"Use estricto"; // habilitar el modo estricto dentro de esta función
barra var;
función baz () {}
eliminar foo; // SyntaxError (al eliminar el argumento)
Eliminar barra; // SyntaxError (al eliminar la variable)
Eliminar Baz; // SyntaxError (al eliminar la variable creada con la declaración de función)
/ * `longitud` de las instancias de funciones ha {[[configurable]]: false} */
delete (function () {}). longitud; // typeError
}) ();
Además, la eliminación de variables no declaradas (o referencias no resueltas) también arrojará errores de sintaxis:
"Use estricto";
eliminar i_dont_exist; // sintaxerror
La asignación no declarada se comporta de manera similar a las variables no declaradas en modo estricto (excepto que esta vez plantea un error de cotización en lugar de un error de sintaxis):
"Use estricto";
i_dont_exist = 1; // referenceError
Como entiende ahora, todas las restricciones tienen más o menos sentido, porque eliminar variables, declaraciones de funciones y parámetros puede causar tanta confusión. En lugar de ignorar silenciosamente la operación de eliminación, el patrón estricto toma una medida más radical y descriptiva.
Resumir:
Esta publicación de blog terminó siendo bastante larga, por lo que no voy a hablar sobre algo como usar Eliminar para eliminar un objeto de matriz o lo que significa. Puede consultar la explicación especial del artículo del MDC (o leer los estándares y hacer sus propios experimentos).
Aquí hay un breve resumen de cómo funcionan las operaciones de eliminación en JavaScript:
Las declaraciones de variables y funciones son propiedades de objetos activos o objetos globales
Los atributos tienen algunas características, y DontDelete es el atributo que determina si este atributo se puede eliminar.
Variables y declaraciones de funciones en el código global o de función siempre crean atributos con atributos de DontDelete.
Los parámetros de la función siempre son atributos del objeto activo y están acompañados de DontDelete.
Variables y funciones declaradas en el código de evaluación Siempre cree propiedades sin DonTDelete.
Las nuevas propiedades no tienen atributos cuando se crean (por supuesto, tampoco hay DONTDELETE).
El objeto del host puede decidir por su cuenta cómo reaccionar ante la operación Eliminar.
Si desea estar más familiarizado con lo que se describe aquí, consulte la especificación ECMA-262 de la tercera edición.
Espero que puedas disfrutar este artículo y aprender algo nuevo. Cualquier pregunta, sugerencia o corrección es bienvenida.