javascript中的delete使用详解(3)

/* 'baz'也是全局对象的一个属性,
    然而,它通过属性赋值而生成,因此没有DontDelete
    这就是为什么它可以被删除*/
GLOBAL_OBJECT.baz = "baz";
delete GLOBAL_OBJECT.baz; // true
typeof GLOBAL_OBJECT.baz; // "undefined"

1.5、内建和DontDelete | Build-ins and DontDelete

所以这就是所有这一切发生的原因:属性的一个特殊的内部属性控制着该属性是否可以被删除。 注意:内建对象的一些属性拥有内部属性 DontDelete,因此不能被删除; 特殊的 arguments 变量(如我们所知的,活化对象的属性)拥有 DontDelete; 任何函数实例的 length (返回形参长度)属性也拥有 DontDelete:

复制代码 代码如下:


(function() {
    //不能删除'arguments',因为有DontDelete
    delete arguments; // false;
    typeof arguments; // "object"

//也不能删除函数的length,因为有DontDelete
    function f() {};
    delete f.length; // false;
    typeof f.length; // "number"
}) ();

与函数 arguments 相关联的属性也拥有 DontDelete,同样不能被删除

复制代码 代码如下:


(function(foo,bar) {
    delete foo; // false
    foo; // 1

delete bar; // false
    bar; // "bah"
}) (1,"bah");

1.6、未声明的变量赋值 | Undeclared assignments
你可能记得,未声明的变量赋值会成为全局对象的属性,除非这一属性在作用域链内的其他地方被找到。 而现在我们了解了属性赋值和变量声明的区别——后者生成 DontDelete 而前者不生成——这也就是为什么未声明的变量赋值可以被删除的原因了。

复制代码 代码如下:


var GLOBAL_OBJECT = this;

/* 通过变量声明生成全局对象的属性,拥有DontDelete */
var foo = 1;

/* 通过未声明的变量赋值生成全局对象的属性,没有DontDelete */
bar = 2;

delete foo; // false
delete bar; // true
注意:内部属性是在属性生成时确定的,之后的赋值过程不会改变已有的属性的内部属性。 理解这一区别是重要的。

/* 'foo'创建的同时生成DontDelete */
function foo() {};

/* 之后的赋值过程不改变已有属性的内部属性,DontDelete仍然存在 */
foo = 1;
delete foo; // false;
typeof foo; // "number"

/* 但赋值一个不存在的属性时,创建了一个没有内部属性的属性,因此没有DontDelete */
this.bar = 1;
delete bar; // true;
typeof bar; // "undefined"

二、Firebug 的混乱 | Firebug confusion

那么, firebug 中发生了什么? 为什么在控制台中声明的变量能够被删除,而不是想我们之前讨论的那样? 我之前说过,Eval code 在它处理变量声明时有一个特殊的行为: 在 Eval code 中声明的变量事实上生成一个没有 DontDelete 的属性。

复制代码 代码如下:


eval('var foo = 1;');
foo; // 1
delete foo; // true
typeof foo; // "undefined"

在函数代码中也是一样:

复制代码 代码如下:


(function() {
    eval('var foo = 1;');
    foo; // 1
    delete foo; // true
    typeof foo; // "undefined"
}) ();

而这就是 Firebug 中异常行为的原因了。 所有在控制台中的调试文本似乎是以 Eval code 来编译和执行的,而不是在全局或函数代码中执行。 显然,其中的变量声明最终都生成了不带 DontDelete 的属性,所以可以被删除。 所以要小心普通的全局代码和 Firebug 控制台中代码的区别。

2.1、通过eval删除变量 | Delete variables via eval
这个有趣的 eval 行为,结合 ECMAScript 的另一个方面可以在技术上允许我们删除那些原本不能删除的属性。 这个方面是关于函数声明——在相同的执行上下文中它们能覆盖同名的变量:

复制代码 代码如下:


function x() { };
var x;
typeof x; // “function”


那么为什么函数声明拥有优先权而能覆盖同名变量(或者换句话说,变量对象(Variable object)的相同属性)呢? 这是因为函数声明的实例化过程在变量声明之后,因此可以覆盖它们。

(译者按:函数声明只能覆盖声明而未赋值的同名变量,如果在声明时赋值了值(e.g. var x = 1)则赋值值的过程在函数初始化之后,函数声明反而被变量赋值所覆盖,如下:)

复制代码 代码如下:


var x = 1;
function x() { };
typeof x; // "number"

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wdgsjx.html