美文网首页
什么是纯粹的JS对象??

什么是纯粹的JS对象??

作者: Yuxin_Liu | 来源:发表于2017-06-02 11:33 被阅读0次

    昨天我们的分享会聊到ES6的collections部分,回头我看了下es6-in-depth,里面有这么一句话:“纯粹的对象不可遍历,也就是,它们不能配合for-of
    循环或...操作符等语法。”
    阿咧?!纯粹的对象是什么鬼👻。。。

    传统的JS对象都是不纯粹的

    var obj = {},你觉得obj是个纯粹的对象嘛?答案是否定的。
    控制台里敲上上线的语句,然后看看obj是什么:

    你可能觉得obj = {},它就什么都没有了,但实际上{}这个东西的声明方式是通过原型链继承了Object,也就生来自带了Object的一系列内置属性和方法,不信你可以继续验证:


    所以说,
    var obj = {}相当于是执行了这个语句 var obj = Object.create(Object.prototype)

    那么到这里为止,我们就可以知道var obj = {}声明得到的obj,它一点儿都不纯粹。然而悲催的是,虽然它生来自带了一串东西,但是这些东西不是enumerable的,所以又不能被遍历出来。用obj.propertyIsEnumerable()来判断,都是false;用for...in遍历,毛线都没有。

    怎么才能纯粹?

    答案是Object.create(null),我们可以先验证一下:


    没有那一串内置属性和方法了,干干净净的。而且完全不是继承Object得来的:

    为什么是纯粹的?

    那就要看下Object.create()是怎么实现的了... 这里是一段Object.create()的polyfill:

    if (typeof Object.create != 'function') {
      // Production steps of ECMA-262, Edition 5, 15.2.3.5
      // Reference: http://es5.github.io/#x15.2.3.5
      Object.create = (function() {
        //为了节省内存,使用一个共享的构造器
        function Temp() {}
    
        // 使用 Object.prototype.hasOwnProperty 更安全的引用 
        var hasOwn = Object.prototype.hasOwnProperty;
    
        return function (O) {
          // 1. 如果 O 不是 Object 或 null,抛出一个 TypeError 异常。
          if (typeof O != 'object') {
            throw TypeError('Object prototype may only be an Object or null');
          }
    
          // 2. 使创建的一个新的对象为 obj ,就和通过
          //    new Object() 表达式创建一个新对象一样,
          //    Object是标准内置的构造器名
          // 3. 设置 obj 的内部属性 [[Prototype]] 为 O。
          Temp.prototype = O;
          var obj = new Temp();
          Temp.prototype = null; // 不要保持一个 O 的杂散引用(a stray reference)...
    
          // 4. 如果存在参数 Properties ,而不是 undefined ,
          //    那么就把参数的自身属性添加到 obj 上,就像调用
          //    携带obj ,Properties两个参数的标准内置函数
          //    Object.defineProperties() 一样。
          if (arguments.length > 1) {
            // Object.defineProperties does ToObject on its first argument.
            var Properties = Object(arguments[1]);
            for (var prop in Properties) {
              if (hasOwn.call(Properties, prop)) {
                obj[prop] = Properties[prop];
              }
            }
          }
    
          // 5. 返回 obj
          return obj;
        };
      })();
    }
    

    从代码里很明显能看到create的操作过程:
    判断,然后把O本身的属性(并没有Object里面内置的属性)一个个赋值给用临时构造器Temp生成的obj上,作为obj的属性。所以如果O是null的话,O没有属性,obj也就什么都没有。

    纯粹了又能怎样

    噢那纯粹了的话好处可多了。
    如果拿不纯粹的空对象做计算的话,totally懵逼的好嘛!
    ({} + 1).length === 16 //true !!


    当然啦,如果你弄得清楚是因为Object.valueOf()Object.toString()在背后搞的鬼也算还好,但这种东西看到了真的只想说“扎心了老铁”。

    那如果拿纯粹的对象做计算的话,sorry,I'm pure and I do not have the 'valueOf' and the 'toString' to help me calculating ...


    用一句别人的话来说“「纯粹」的对象适合用于存储键值对数据,而且没有隐式的类型转换,更加直观。”

    当然了,除了继承了Object.prototype这点,Object.create(null){}之间没有别的区别了,在操作对象这一点上完全一致,存取的性能没差啦。但如果并不care自己的空对象继承了Object的话,宝宝们还是使用{}来声明吧,因为在创建性能上{}Object.create(null) 快了20倍呢!!!

    相关文章

      网友评论

          本文标题:什么是纯粹的JS对象??

          本文链接:https://www.haomeiwen.com/subject/jsgyfxtx.html