JavaScript核心原理解析--delete 0

758 阅读4分钟

今年干了人生中几件大事,结婚,老婆怀孕这也意味着我马上要当爸爸了,在这里恭喜自己^_^!!,但是随之而来的是压力,回想我这两年的工作,突然有了危机我和刚毕业的时候没有任何的进步,所以得益于公司的福利,有机会在极客时间上充充电,所以决定每天学点东西把自己的知识丰富起来,从今天起会不定期的更新JavaScript核心原理解析的心得,从基础补起(一直在计划,从来未实践),所以希望我可以坚持下去。

知识点归纳

首先先上结论:

delete 不是要操作 0 或 x 这样的单个记号或标识符(例如变量)。delete是要删除一个表达式的结果,而表达式的结果要不是值,要不是引用,如果是引用,也就是 “删除对象的成员” ,那么这个语句就是有意义的,如果是删除值则是毫无意义的,所以直接返回true。

delete 如果是删除只读的属性会返回false ,引申出来的要知道 null 是个值,而undefined 不是值而是一个全局对象上的属性,且是只读的的。因为undefined 是可以被修改的,所以真正的未定义通常用表达式 “void 0 ” 表示

那么它真正需要的语法其实是

delete obj.x

"delete x" 只不过因为全局对象的成员可以用全局变量的形式来存取,所以当x 表示是全局变量的时候这个语法才有意义,表示删除的是全局对象上的x成员

如果删除的是一个值会怎么样?

任何语言不可能把一个值删除,然后导致这个值在程序中不能使用,所以 JavaScript 认为“所有删除值的 delete 就直接返回 true

delete {}    	//true
delete 0	//true

所以 “delete 表达式”归根到底,是在删除一个表达式的的结果(Result)(ECMAScript 约定:任何表达式计算的结果(Result)要么是一个值,要么是一个引用。),而不是在删除 x 表达式,所以上面两个语句的结果都是true。

就拿第一个来说明,虽然从程序员的传统上来说,{} 是个引用类型,但是 delete XXX ,XXX 是个表达式,这个表达式的结果就是值{} , {},0这种表达式又被称谓单值表达式(在 JavaScript 中,有两个东西可以被执行并存在执行结果(Result),包括语句和表达式。比如你用eval()来执行一个字符串,那么实际上,你执行的是一个语句,并返回了语句的值;而如果你使用一对括号来强制一个表达式执行,那么这个括号运算得到的,就是这个表达式的值。)。

delete null 和 delete undefined 的奇妙展示

我想大多数人和我一样认为这是在删除一个值,所以结果应该都是true,但是执行结果啪啪打脸。 "delete undefined" 是个false,因为undefind 居然是全局变量的属性,还是只读的。

下面请看大神是如果解释的。
早期的JavaScript中,undefined是一个特殊值,是在运行期中通过void运算,或者不返回值的函数,又或者一个声明了但未赋值的变量,等等类似这样的情况来“计算得到”的。所以在JavaScript的早期版本中,你没有办法直接判断“undefined是undefined”,例如无法写出“x === undefined”这样的代码,而你只能写类似“typeof(x) ==='undefined'”这样的代码。

后来(其实也没有太久),规范就约定把undefined作为可以缺省访问的名字,类似于null。但是这个时候就带来了一个矛盾,因为这个undefined很重要,早期的绝大多数框架或引擎都把它作为一个“全局名字”给声明了。也就是说,ECMAScript现在既没有办法将它规范成一个keyword,也没有办法处理成保留字等等,它看起来像null,但又没有办法在规范层面强制它。所以……ECMAScript就搞了一个“奇招”:

我们把undefined声明成全局的属性,怎么样?!

嗯嗯,很好。所以你看,现在的引擎上面undefined看起来长得跟null值差不多,而且在ECMAScript规范中它们都还是平级的(是原始值),而且它们的作用也很接近,最后他们都还是从最初的JavaScript 1.x中就存在的概念,但是undefined/null两者却在实现上完全不同:undefined是一个全局属性,而null是一个关键字。

由于undefined是全局属性,所以delete undefined其实就是delete global.undefined,是删除引用,而不是删除值。而这个属性是只读的,所以就返回false了。

例如你可以试试下面的代码:

Object.getOwnPropertyDescriptor(global, 'undefined')

{ value: undefined,
  writable: false,
  enumerable: false,
  configurable: false }

思考题

  • delete x 中,如果 x 根本不存在,会发生什么?
  • delete object.x 中,如果 x 是只读的,会发生什么?

答案

  1. true

a={
    b:5,
    c:function(){
        console.log(delete b);
    }
};
a.c();
  1. false