zoukankan      html  css  js  c++  java
  • [Effective JavaScript 笔记]第40条:避免继承标准类

    ECMAScript标准库里配备了许多重要的类,如Array,function,以及Date等。扩展这些类生成子类可以方便完成很多工作,但它们的定义具有很多特殊的行为,所以很难写出行为正确的类。

    Array示例

    一个操作文件系统的库可能希望创建一个对象的目录,该目录继承了数组的所有行为。

    function Dir(path,entries){
      this.path=path;
      for(var i=0,n=entries.length;i < n;i++){
        this[i]=entries[i];
      }
    }
    Dir.prototype=Object.create(Array.prototype);
    

    运行下面这段代码,并没有得到预期的行为。

    var dir=new Dir('/tmp/mysite',['index.html','script.js','style.css']);
    dir.length;//0

    失败的原因

    length属性只对在内部被标记为“真正的”数组的特殊对象起作用。ECMAScript标准规定它是一个不可见的内部属性,称为[[Class]]。它的值只是一个简单的标签,并不是js真正有内部类系统。数组对象的[[Class]]值是"Array",函数对应的[[Class]]是"Function"。下面这个表是ECMAScript中定义的完整的[[Class]]属性值集合。

    image

    解密length

    那么神奇的[[Class]]属性对length做了什么呢?事实上,length的行为只被定义在内部属性[[Class]]的值为"Array"的特殊对象中。对于这些对象,js保持length属性与该对象的索引属性的数量同步。如果给该对象添加了更多的索引属性,length属性会自动增加。如果减少了length属性,也会自动删除任何索引大于该新值的索引属性。
    当我们扩展Array类时,子类的实例并不是通过new Array()或字面量[]语法创建的。所以Dir实例的[[Class]]属性值为"Object"。
    使用默认的Object.prototype.toString()方法可以通过查询其接收者的内部[[Class]]属性来创建对象的通用描述。可以传递任何给定的对象来显式地调用它。

    var dir=new Dir('/',[]);
    Object.prototype.toString.call(dir);//"[Object Object]"
    Object.prototype.toString.call([]);//"[Object Array]"

    结果Dir的实例未继承数组的length属性所期望的特殊行为。

    更好的实现

    定义一个entries数组的实例属性。

    function Dir(path,entries){
      this.path=path;
      this.entries=entries;
    }
    

    在原型中重新定义Array的方法,将这些相应的方法委托给entries属性来实现。

    Dir.prototype.forEach=function(f,thisArg){
      if(typeof thisArg==='undefined'){
        thisArg=this;
      }
      this.entries.forEach(f,thisArg);
    }
    

    ECMAScript标准库中的大多数构造函数都有类似的问题。某些属性或方法期望具有正确的[[Class]]属性或其他特殊的内部属性,然而子类却无法提供。基于这个原因,最好避免继承以下的标准类:Array,Boolean,Date,Function,RegExp,String。

    提示

    • 继承标准类往往会由于一些特殊的内部属性(如[[Class]])而被破坏

    • 使用属性委托优于继承标准类

  • 相关阅读:
    微软WP7本地数据库之Sqlite编程技巧(转)
    AutoResetEvent详解
    桥接模式的简单分析
    解决VS2008 调试启动特别慢
    软件概要设计
    解决windows8不能安装ZUNE的问题
    CDATA的对特殊字符作用说明
    DataTable对象在内存中的使用(二)
    DataTable对象在内存中的使用(一)
    关于MVC3 CODE FIRST的安装
  • 原文地址:https://www.cnblogs.com/wengxuesong/p/5602793.html
Copyright © 2011-2022 走看看