deletion works in Javascript:
- Variables and function declarations are properties of either Activation or Global objects.
- Properties have attributes, one of which — DontDelete — is responsible for whether a property can be deleted.
- Variable and function declarations in Global and Function code always create properties with DontDelete.
- Function arguments are also properties of Activation object and are created with DontDelete.
- Variable and function declarations in Eval code always create properties without DontDelete.
- New properties are always created with empty attributes (and so without DontDelete).
- Host objects are allowed to react to deletion however they want.
var o = { x: 1 }; delete o.x; // true o.x; // undefined
var x = 1; delete x; // false x; // 1
function x(){} delete x; // false typeof x; // "function"
>>> var sum = function(a, b) {return a + b;} >>> var add = sum; >>> delete sum true >>> typeof sum; "undefined"
(function(foo, bar){ delete foo; // false foo; // 1 delete bar; // false bar; // 'blah' })(1, 'blah');
(function(){ /* can't delete `arguments`, since it has DontDelete */ delete arguments; // false typeof arguments; // "object" /* can't delete function's `length`; it also has DontDelete */ function f(){} delete f.length; // false typeof f.length; // "number" })();What is
var GLOBAL_OBJECT = this; /* create global property via variable declaration; property has DontDelete */ var foo = 1; /* create global property via undeclared assignment; property has no DontDelete */ bar = 2; delete foo; // false typeof foo; // "number" delete bar; // true typeof bar; // "undefined"
/* `foo` is created as a property with DontDelete */ function foo(){} /* Later assignments do not modify attributes. DontDelete is still there! */ foo = 1; delete foo; // false typeof foo; // "number" /* But assigning to a property that doesn't exist, creates that property with empty attributes (and so without DontDelete) */ this.bar = 1; delete bar; // true typeof bar; // "undefined"
Eval code has a special behavior when it comes to variable declaration. Variables declared within Eval code are actually created as properties without DontDelete:
eval('var foo = 1;');
foo; // 1
delete foo; // true
typeof foo; // "undefined"
and, similarly, when called within Function code:
(function(){
eval('var foo = 1;');
foo; // 1
delete foo; // true
typeof foo; // "undefined"
})();
Deleting variables via eval§
This interesting
eval
behavior, coupled with another aspect of ECMAScript can technically allow us to delete non-deletable properties. The thing about function declarations is that they can overwrite same-named variables in the same execution context:
function x(){ }
var x;
typeof x; // "function"
Note how function declaration takes precedence and overwrites same-named variable (or, in other words, same property of Variable object). This is because function declarations are instantiated after variable declarations, and are allowed to overwrite them. Not only does function declaration replaces previous value of a property, it also replaces that property attributes. If we declare function via
eval
, that function should also replace that property’s attributes with its own. And since variables declared from within eval
create properties without DontDelete, instantiating this new function should essentially remove existing DontDelete attribute from the property in question, making that property deletable (and of course changing its value to reference newly created function).
var x = 1;
/* Can't delete, `x` has DontDelete */
delete x; // false
typeof x; // "number"
eval('function x(){}');
/* `x` property now references function, and should have no DontDelete */
typeof x; // "function"
delete x; // should be `true`
typeof x; // should be "undefined"
http://perfectionkills.com/understanding-delete/#summary
No comments:
Post a Comment