视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
JavaScript原型继承之构造函数继承_javascript技巧
2020-11-27 21:00:24 责编:小采
文档


上回说到《JavaScript 原型继承之基础机制》,这一篇将具体说说构造函数的继承。

从一个简单的示例开始,创建描述人类的 People 构造函数:
代码如下:
function People(){
this.race = '愚蠢的人类';
}

然后,创建描述黄种人的 Yellow 构造函数:
代码如下:
function Yellow(name, skin){
this.name = name;
this.skin = skin;
}

要使得黄种人 Yellow 能继承人类 People 对象,在 JavaScript 中可以通过多种方式模拟实现。

1、对象冒充(Object Masquerading)

对象冒充,简单地说就是把一个定义抽象类的构造函数当作常规函数使用,实现伪继承:
代码如下:
function Yellow(name, skin) {
this._extend = People;
this._extend();
delete this._extend; //删除对 People 的引用
this.name = name;
this.skin = skin;
}
//实例化 yellow1
var yellow1 = new Yellow('小明', '黄皮肤');
console.log(yellow1.name); //小明
console.log(yellow1.race); //愚蠢的人类

在这段代码中,为 Yellow 添加私有方法 _extend,由于函数本身只是以引用的形式存在,执行时会自动调用 People方法,并传入 Yellow 构造函数的 name 参数。而 Yellow 对象的自身属性和方法,必须在上述过程结束,清空对外部方法的引用后再进行定义。

注:通过对象冒充可以实现多重继承

2、call / apply 方法

通过 call / apply 方法实现继承可能更为简单,不需要任何繁琐的操作:
代码如下:
function Yellow(name, skin) {
People.apply(this, arguments);
this.name = name;
this.skin = skin;
}
//实例化 yellow2
var yellow2 = new Yellow('大卫', '黑皮肤')
console.log(yellow2.name); //大卫
console.log(yellow2.race); //愚蠢的人类
这里为 apply 传入 arguments 数组,也可以使用 new Array 或字面量数组。

3、原型链(Prototype Chaining)

第一种原型继承方法是把对象的原型指向父类的某个实例:
代码如下:
Yellow.prototype = new People();
Yellow.prototype.constructor = Yellow; //初始的 prototype 被完全清空,所以最好将 constructor 重置
var yellow3 = new Yellow('小王', '黄皮肤');
console.log(yellow3.race); //愚蠢的人类

以上代码可以这样反向理解,yellow3 实例本身找不到 race 属性,而它原型上的 race 属性又恰好是 People 对象的实例的 race 属性。

如果对于 People 对象来说,其属性写入了原型中,则无需实例化,只需将 Yellow 的 prototype 属性指向 People的 prototype 属性:
代码如下:
function People(){};
People.prototype.race = '愚蠢的人类';
Yellow.prototype = People.prototype;
Yellow.prototype.constructor = Yellow;

这样做不进行实例化操作,只是指针的改变,非常环保。但由于引用类型的关系,Yellow 和 People 指向了同一个原型对象,也就是说对 Yellow.prototype.constructor 的修改实际上破坏了 People 的原型对象。

既然如此,可以借助一个空的中继对象,绕过父类的原型:
代码如下:
var F = function(){};
F.prototype = People.prototype;
Yellow.prototype = new F();
Yellow.prototype.constructor = Yellow;

下载本文
显示全文
专题