博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Effective JavaScript Item 40 避免继承标准类型
阅读量:5980 次
发布时间:2019-06-20

本文共 1721 字,大约阅读时间需要 5 分钟。

本系列作为Effective JavaScript的读书笔记。

 

ECMAScript标准库不大。可是提供了一些重要的类型如ArrayFunctionDate。在一些场合下。你或许会考虑继承当中的某个类型来实现特定的功能。可是这样的做法并不被鼓舞。

 

比方为了操作一个文件夹。能够让文件夹类型继承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);// extends Arrayvar dir = new Dir("/tmp/mysite", ["index.html", "script.js", "style.css"]);dir.length; // 0

可是能够发现。dir.length的值是0,而不是期待中的3

 

发生这样的现象的原因在于:仅仅有当对象是真正的Array类型时,length属性才会起作用。

 

ECMAScript标准中。定义了一个不可见的内部属性被称为 [[class]]。该属性的值仅仅是一个字符串,所以不要被误导觉得JavaScript也实现了自己的类型系统。所以,对于Array类型,这个属性的值就是“Array”。对于Function类型。这个属性的值就是“Function”。下表是ECMAScript定义的全部[[class]] 值:

那么当对象的类型确实是Array时,length属性的特别之处就在于:length的值会和该对象中被索引的属性个数保持一致。比方对于一个数组对象arrarr[0]arr[1]就表示该对象有两个被索引的属性。那么length的值就是2。当加入了arr[2]的时候。length的值会被自己主动同步成3

相同地,当设置length值为2时。arr[2]会被自己主动设置成undefined

 

可是当继承Array类型并创建实例时,该实例的 [[class]] 属性并非Array。而是Object。因此length属性不能正确的工作。

 

JavaScript中,也提供了用于查询 [[class]] 属性的方法,即使用Object.prototype.toString方法:

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

因此,更好的实现方法是使用组合而不是继承:

function Dir(path, entries) {	this.path = path;	this.entries = entries; // array property}Dir.prototype.forEach = function(f, thisArg) {	if (typeof thisArg === "undefined") {		thisArg = this;	}	this.entries.forEach(f, thisArg);};

以上代码将不再使用继承。而是将一部分功能代理给内部的entries属性来实现。该属性的值是一个Array类型对象。

 

ECMAScript标准库中,大部分的构造函数都会依赖内部属性值如 [[class]] 来实现正确的行为。对于继承这些标准类型的子类型。无法保证它们的行为是正确的。

因此。不要继承ECMAScript标准库中的类型如:

Array Boolean Date Function NumberRegExpString

 

总结

  1. 继承标准类型可能会导致子类的行为不对,由于标准类型会依赖于内部属性诸如 [[class]]
  2. 优先使用组合的方式来实现功能。而不是使用继承。

你可能感兴趣的文章
Spring可扩展Schema标签
查看>>
c++ STL unique , unique_copy函数
查看>>
http://miicaa.yopwork.com/help/overall/
查看>>
浅谈关于特征选择算法与Relief的实现
查看>>
mybatis-spring 项目简介
查看>>
Wireshark抓取RTP包,还原语音
查看>>
Behavioral模式之Memento模式
查看>>
Work Management Service application in SharePoint 2016
查看>>
Dos 改动IP 地址
查看>>
Laravel 源码解读:php artisan make:auth
查看>>
【转】ionic run android 成功launch success,但是genymotion虚拟机没有显示
查看>>
苹果在GitHub上正式开源iOS内核源码
查看>>
测试人员面临的测试挑战和必备技能
查看>>
使用Flutter之后,我们的CPU占用率降了50%
查看>>
同事反馈环:为什么度量和会议还不够充分
查看>>
[转]十问 Linux 虚拟内存管理 (glibc)
查看>>
老司机带你深入浅出 Collection
查看>>
查询系统-vba
查看>>
[译]Spring Session 与 Spring Security
查看>>
python学习笔记(05)
查看>>