Javascript 设计模式学习笔记(2) - 继承(Inheritance) (上)

    继承(Inheritance)

Javascript 继承很复杂, 比其它任何面向对象语言都复杂. Javascript 是少数使用 原型式继承 的语言之一, 这也正是 Javascript 的优点.

继承主要分为两种: 类继承, 原型式继承.

(一) 为什么要继承

代码重用, 易维护. 但是继承会增加对象之间的耦合度, 所以后面会讨论一些办法来对付它.


(二) 类式继承

模拟类式继承, 先给出一个父类

/* Class Person. */
function Person(name) {
  this.name = name;
}

Person.prototype.getName = function(){
  return this.name;
}

这个类作为下面例子的父类.

(1) 原型链 ( 我们现在讨论的是 类式继承 )  

创建一个继承 Person 的类 Author :

/* Class Author. */

function Author(name, books) {
  Person.call(this, name);                       // 1
  this.books = books;                            // 2
}
//------- 分割线 ---------
Author.prototype = new Person();                 // 3
Author.prototype.constructor = Author;           // 4
Author.prototype.getBooks = function() {         // 5
  return this.books;
}

上面的第1句好理解, 像在Java里一样, 调用父类的构造函数. 有点说头的就是3 , 4句. 我在这里多做些关于 constructor, obj.prototype and [[Prototype]] 的笔记.


function Author() {
// some code goes here.
}

如图:

下面分析一下 内置属性 [[Prototype]], obj.prototype, constructor 这三个东西

首先明确一下叫法, [[Prototype]]指向的对象叫做对象的原型对象, prototype指向的对象叫做 prototype对象. 为什么要分开, 因为上图也显示了这两个对象是不同的.

我们知道 Javascript 中, 每个对象都有 原型对象, 但每个对象却不一定有 prototype 属性, 如果没有 prototype 属性, 自然也就不存在 prototype对象. 

只有函数对象才有 prototype 这个属性, 如上图的 Author() .

当定义 Author ( function Author() {} ) 后, 上图的链式结构就已经存在了. 请特别注意一下 Author.prototype 对象的 constructor 属性, 它现在已经存在了, 并且指回 Author 记住这个.

* [[Prototype]] , prototype 区别及作用?

- [[Prototype]]指明了当前对象( Author )的原型对象, 是和 Author 真正相关的东西.. [[Prototype]] = 我的构造的 prototype 属性的值.

- 仔细想一下第一条, 正好说明了 prototype 属性的作用, 这个属性是用来 初值化 由 Author 构造出来的实例的 [[Prototype]] 属性.

假如有:

var patrick = new Author();

那么 patrick 的 [[Prototype]] 的值就是 Author.prototype 的值. 所以说, Author.prototype 属性与 Author 类更加息息相关, 为了好理解, 说的极端点 Author.prototype 是为其实例服务的, 和 Author 类本身关系不大.

// 创建一个实例

var patrick = new Author();


--------------- 回到上面话题 ---------------

/* Class Author. */

function Author(name, books) {
  Person.call(this, name);                       // 1
  this.books = books;                            // 2
}
//------- 分割线 ---------
Author.prototype = new Person();                 // 3
Author.prototype.constructor = Author;           // 4
Author.prototype.getBooks = function() {         // 5
  return this.books;
}

我们想让 Author 类继承 Person类, 设置Author.prototype对象为Person的一个实例就行, 因为手动改变了 Author.prototype , constructor也就不是不是原来的 Author() , 而变成了 Person(). 所以要手动把 constructor 设置回去, 设成 Author.

* 为什么 constructor 会变?

- 像第一个图里那样, constructor 是在创建Author类的时候在Author.prototype上自动创建的属性并指回Author. 当后来手动改变了Author.prototype = new Person() 后. 这时的

constructor 是什么? 假设new 出来的Person 为 p. 那么 查找 p.constructor , 在 p 里没有此属性, 沿着原型链往上找, p 的原型是 Person.prototype , 这里有 constructor 属性, 但是它的值是指向 Person() 构造函数. 所以要上面代码的第4句, 手动设置回成Author.
下一话题.

(2) extend 函数

给出一个extend() , 类似其它语言的 extend 关键字

/* Extend function */

function extend(subClass, superClass) {
  var F = function() {};
  F.prototype = superClass.prototype;
  subClass.prototype = new F();
  subClass.prototype.constructor = subClass();
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值