zoukankan      html  css  js  c++  java
  • Understanding delete

    简述

            我们都知道无法通过delete关键字针对变量和函数进行操作,而对于显示的对象属性声明却可以进行,这个原因需要深究到js的实现层上去,让我们跟随 Understanding delete 来探究一番,另外本文并不考虑浏览器的兼容性实现问题。

    理论

                为什么我们可以这样:

      var o = { x: 1 };
      delete o.x; // true
      o.x; // undefined

             却无法这样

    var x = 1;
      delete x; // false
      x; // 1

                   其实,这要涉及到执行上下文的概念,而每个执行上下文都对应一个变量对象VO,在全局上下文中VO就是全局对象window,在函数上下文中,VO也是活动地向AO,而在eval中的代码在执行时,其执行上下文也就是调用eval的上下文。

             在上下文中定义的变量,函数声明以及函数的入参和AO特有的arguments对象等等,都属于VO(AO)的属性。而对于VO这样的实体对象而言,它也有自己的元数据,也就是在ES5中对象的数据特性:[[configurable]],[[enurable]],[[value]],[[writable]]。而对于VO的属性,默认的[[configurable]]是false,这样就无法针对这些变量使用delete操作。而对于显示的对象属性赋值,比如obj.name = “a”,对于name属性的[[configurable]]特性是true,因此可以删除。

    var GLOBAL_OBJECT = this;
    
      /*  `foo` is a property of a Global object.
          It is created via variable declaration and so has DontDelete attribute.
          This is why it can not be deleted. */
    
      var foo = 1;
      delete foo; // false
      typeof foo; // "number"
    
      /*  `bar` is a property of a Global object.
          It is created via function declaration and so has DontDelete attribute.
          This is why it can not be deleted either. */
    
      function bar(){}
      delete bar; // false
      typeof bar; // "function"
    
      /*  `baz` is also a property of a Global object.
          However, it is created via property assignment and so has no DontDelete attribute.
          This is why it can be deleted. */
    
      GLOBAL_OBJECT.baz = 'blah';
      delete GLOBAL_OBJECT.baz; // true
      typeof GLOBAL_OBJECT.baz; // "undefined"

               另外,函数的length属性也是不可以删除的。

               而对于未初始化的变量赋值,我们知道未初始化的变量默认为全局变量,VO的属性确定是在进入上下文阶段,因此未初始化变量并不会成为VO的属性,[[configurable]]仍未true,可以删除。

    /* `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"

                凡是都有例外,对于delete操作也难免。上述提到的第三种上下文--eval上下文,有个特殊的行为,就是在eval中声明的变量,函数可以在调用上下文中删除。

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

    ES5严格模式

             ES5的严格模式与上述提到的行为不同,它不准许delete删除函数入参,变量和函数,以及函数对象的length。删除未声明的 变量也会抛出语法错误SyntaxError。

    (function(foo){
    
      "use strict"; // enable strict mode within this function
    
      var bar;
      function baz(){}
    
      delete foo; // SyntaxError (when deleting argument)
      delete bar; // SyntaxError (when deleting variable)
      delete baz; // SyntaxError (when deleting variable created with function declaration)
    
      /* `length` of function instances has { [[Configurable]] : false } */
    
      delete (function(){}).length; // TypeError
    
      delete i_dont_exist; // deleting undeclared variable (or in other words, unresolved Referece) throws SyntaxError
    })();

    总结

    •   需要知道有哪几种上下文,每个上下文对应一个VO
    •   上下文中定义的函数、变量、入参、arguments等都是VO的属性,[[configurable]]为false
    •   eval上下文的特殊性
    •   未声明变量并不是VO的属性,[[configurable]]为true
    •   删除宿主对象属性时需小心,可能有意外发生,取决于js引擎的具体实现
  • 相关阅读:
    WDA学习(14):Colors Cell and Input Enable to ALV Column
    JavaScript try-catch语句(错误处理)
    constructor
    input file 重复上传同一张图片失效的解决办法
    input下拉带输入框
    box-shaw四边阴影详解
    苹方字体合集
    两个div不同高度并排显示
    弹窗库
    webstorm破解安装版本
  • 原文地址:https://www.cnblogs.com/accordion/p/4261313.html
Copyright © 2011-2022 走看看