《JS高级程序设计》第6章读书笔记:对象继承(一)原型链
2017-08-25 22:39
197 查看
《JS高级程序设计》第6章的读书笔记
创建对象(一)工场模式和构造函数模式
创建对象(二)原型模式和组合模式
创建对象(三)再探原型
对象继承(一)原型链
对象继承 (二)借用构造函数和组合继承
对象继承(三)原型式继承和寄生式继承
对象继承(四)寄生组合式继承
更为可怕的是:《JS高级程序设计》阐述6种对象的方式,虽然其中只有一种方式是常用的。学习了这部分内容,我觉得,如此繁杂的继承方式,即使当初创造JS的作者也会觉得吃惊。
还是直接看实现原型链的代码吧
我们可以看到子类型的实例
继承后的结果如下图:
而实现继承的关键在于这行代码
用自然语言表述的话:重写子类的原型对象为父类的实例对象。
注意一个异常:继承之后,instance.constructor现在指向SuperType,这是因为子类型原型被重写后,子类原型没有constructor这个属性了。
造成的结果:原型搜索结果被扩展,访问属性时,会先后搜索实例对象,子类原型对象,父类原型对象,Object的原型
基于最上面的基础代码
第二种方式:isPropertyOf方法
基于最上面的基础代码
注意:通过原型链实现继承时,不能使用对象字面量方法创建原型方法
很简单:重写原型后,SubType.prototype就没有[[prototype]]属性指向父类型的原型对象
但是在用原型链实现集成继承时,原先的实例属性成了子类型的原型属性。(因为子类型的原型是父类型的实例。)
具体看下面这段代码:
具体看代码:
上述代码没有彻底实现自定义子类型的意愿。
创建对象(一)工场模式和构造函数模式
创建对象(二)原型模式和组合模式
创建对象(三)再探原型
对象继承(一)原型链
对象继承 (二)借用构造函数和组合继承
对象继承(三)原型式继承和寄生式继承
对象继承(四)寄生组合式继承
1 前言
我前后写了3篇博文阐述创建对象的4种方式。更为可怕的是:《JS高级程序设计》阐述6种对象的方式,虽然其中只有一种方式是常用的。学习了这部分内容,我觉得,如此繁杂的继承方式,即使当初创造JS的作者也会觉得吃惊。
2 原型链(继承)
原型链自然是基于原型的。我在之前的博客:JS高级程序设计》第6章读书笔记:创建对象(二)原型模式和组合模式以及《JS高级程序设计》第6章读书笔记:创建对象(三)再探原型 两篇文章阐述了原型的概念和细节。还是直接看实现原型链的代码吧
function SuperType() { this.property = true; } SuperType.prototype.getSuperValue = function() { return this.property; } function SubType() { this.subproperty = false; } SubType.prototype = new SuperType(); // 这里是关键 SubType.prototype.getSubValue = function() { return this.subproperty; } var instance = new SubType(); console.log(instance.getSuperValue()); // true
我们可以看到子类型的实例
instance能够调用父类型的方法
getSuperValue,所以我们可以说子类型继承了父类型。
继承后的结果如下图:
而实现继承的关键在于这行代码
SubType.prototype = new SuperType(); // 这里是关键
用自然语言表述的话:重写子类的原型对象为父类的实例对象。
注意一个异常:继承之后,instance.constructor现在指向SuperType,这是因为子类型原型被重写后,子类原型没有constructor这个属性了。
造成的结果:原型搜索结果被扩展,访问属性时,会先后搜索实例对象,子类原型对象,父类原型对象,Object的原型
确定原型和实例的关系
第一种方式:instanceof操作符基于最上面的基础代码
console.log(instance instanceof Object); //true console.log(instance instanceof SuperType); //true console.log(instance instanceof SubType); //true
第二种方式:isPropertyOf方法
基于最上面的基础代码
console.log(Object.prototype.isPrototypeOf(instance)); //true console.log(SuperType.prototype.isPrototypeOf(instance)); //true console.log(SubType.prototype.isPrototypeOf(instance)); //true
谨慎地定义方法
在需要覆盖或者添加超类型中不存在的某个方法时,一定要在替换原型的语句之后SubType.prototype.getSubValue = function(){ //添加超类型之后不存在的某个方法 return this.subproperty; } SubType.prototype.getSuperValue = functipn(){ //覆盖超类型方法 return false; }
注意:通过原型链实现继承时,不能使用对象字面量方法创建原型方法
function SuperType() { this.property = true; } SuperType.prototype.getSuperValue = function() { return this.property; } function SubType() { this.subproperty = false; } SubType.prototype = new SuperType(); SubType.prototype = { // getSubValue: function() { return this.subproperty; }, someOtherMethod: function() { return false; } } SubType.prototype.getSubValue = function() { return this.subproperty; } var instance = new SubType(); console.log(instance.getSuperValue()); // instance.getSuperValue is not a function
很简单:重写原型后,SubType.prototype就没有[[prototype]]属性指向父类型的原型对象
原型链的问题
第1个问题
原型链的问题和原型的问题紧密相关。我们知道,原型问题是包含引用类型值的原型属性会被所有实例共享。所以,我们要在构造函数中,而不是在原型对象中定义属性。因而,构造函数模式和原型模式相结合的组合模式解决了这个问题,成为最常用的创建对象的模式。但是在用原型链实现集成继承时,原先的实例属性成了子类型的原型属性。(因为子类型的原型是父类型的实例。)
具体看下面这段代码:
function SuperType() { this.colors = ['red', 'blue', 'green']; } function SubType() {} SubType.prototype = new SuperType(); let instance1 = new SubType(); instance1.colors.push('black'); console.log(instance1.colors); //[ 'red', 'blue', 'green', 'black' ] let instance2 = new SubType(); console.log(instance2.colors); //[ 'red', 'blue', 'green', 'black' ]
第2个问题
无法再不影响所有对象实例的情况下给超类型传递参数。因为子类型实例共享了子类型原型的属性。具体看代码:
function SuperType(name) { this.name = name; } function SubType() {} SubType.prototype = new SuperType('achao'); let instance1 = new SubType(); console.log(instance1.name); //achao let instance2 = new SubType(); console.log(instance2.name); //achao
上述代码没有彻底实现自定义子类型的意愿。
相关文章推荐
- 《JS高级程序设计》第6章读书笔记:对象继承(三)原型式继承和寄生式继承
- 《JS高级程序设计》第6章读书笔记:继承对象(四)寄生组合式继承
- 《JS高级程序设计》第6章读书笔记:继承对象(二)借用构造函数和组合继承
- 《JS高级程序设计》第6章读书笔记:创建对象(三)再探原型
- [置顶] 《JS高级程序设计》第6章读书笔记:创建对象(一)之工场模式和构造函数模式
- 《JS高级程序设计》第6章读书笔记:创建对象(二)原型模式和组合模式
- JavaScript 利用原型和原型链实现对象继承
- js继承 对象冒充和原型链继承
- 读书笔记--对象、实例、原型、继承
- 面向对象之继承(读书笔记)
- 快学scala 第6章 对象 读书笔记及习题答案代码
- 读书笔记--对象、实例、原型、继承
- JS面向对象(2) -- this的使用,对象之间的赋值,for...in语句,delete使用,成员方法,json对象的使用,prototype的使用,原型继承与原型链
- 读书笔记-C++PrimerPlus-8.2.6 对象、继承和引用10.2.5 修改实现
- 《Python语言及其应用》读书笔记(5)之第6章对象和类(关键词:对象/类)
- javascript高级程序设计第六章:面向对象的程序设计——继承读书笔记
- js 创建对象与原型链继承
- 第6章 面向对象的程序设计 6.3 继承
- JavaScript使用原型和原型链实现对象继承的方法详解
- 【JavaScript高级程序设计】读书笔记之二 —— 理解对象的原型、继承