《JavaScript语言精粹》--第5章:继承

本文介绍JavaScript中类的创建和继承方式,包括伪类和函数化模式两种方法,并探讨它们各自的优缺点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/*
	当一个函数对象被创建时,Function构造器产生的函数对象将会运行类似下面的代码:
*/
this.prototype = {
	constructor: this
};

//--------------------------------------------------------------------------------

/*
	伪类创建
		直接使用new + 构造函数创建伪类
*/
var Cat = function(name) {
	this.name = name;
	this.getName = function() {
		return this.name;
	};
	this.speaks = function() {
		return this.sound || "";
	};
	this.run = function() {
		return "Cat is running";
	};
};

var cat = new Cat("Tom");
console.log(cat.getName());
//输出:
//Tom

//--------------------------------------------------------------------------------

/*
	伪类继承
		将父类实例付给子类实例的原型进行继承
*/
var BlackCat = function(name) {
	this.name = name;
	this.sound = "miao";
	this.getName = function() {
		return "BlackCat'name is " + this.name;
	};
};

BlackCat.prototype = new Cat();

Cat.prototype.swim = function() {
	return "cat can swim!"
};

var blackCat = new BlackCat("Black Tom");
console.log(blackCat.speaks());
console.log(blackCat.getName());
console.log(blackCat.run());
console.log(blackCat.swim());
//输出:
// miao
// BlackCat'name is Black Tom
// Cat is running
// cat can swim! 

//--------------------------------------------------------------------------------

/*
	伪类模式缺点
		伪类没有私有环境,所有属性都是公开的,且无法访问super(父类)的方法
		在使用构造器函数时,若忘记加上new,this将会绑定到全局对象上,这样不但没有扩充新对象,反而破坏了全局变量环境
*/
console.log(blackCat.name);
console.log(blackCat.sound);
//输出:
//Black Tom
//miao
/*
	只能访问到BlackCat类的getName方法,无法访问到父类的getName方法

*/

//--------------------------------------------------------------------------------


/*
	对象说明符
		构造器要接受一大堆参数时,使用一个对象作为参数将会更加友好
*/

//--------------------------------------------------------------------------------

/*
	函数化模式
		相对于伪类的无法保护隐私的特点,我们更应当使用模块模式,模块模式继承包括以下内容:
		4个步骤:
			创建一个新对象
			有选择地定义私有变量和方法
			给这个新对象扩充方法
			返回那个新对象
		spec对象:包含构造器需要构造一个新实例的所有信息
		my对象:一个为继承链中构造器提供秘密共享的容器
		伪码:
			var constructor = function(spec, my) {
				var that;
				//定义其他私有变量
				my = my || {};
				//把共享变量和函数放入my中
				that = {};
				//给that添加特权方法
				return that;
			};
*/

//--------------------------------------------------------------------------------

/*
	利用superior方法可以获得父类方法
*/
// 函数化模式给我们提供了一个处理父类的方法,构造一个superior方法,它取得一个方法名,并返回调用那个方法的函数
Object.prototype.superior = function(name) {
	var that = this,
		method = that[name];
	return function() {
		return method.apply(that, arguments);
	};
};

//--------------------------------------------------------------------------------

/*
	函数化模式优点:
		函数化模式有更好的封装性和信息隐藏能力,而且可以访问父类方法
*/

//继承时,如果需要调用父类方法,则可以通过这个Object扩展方法进行调用
Object.prototype.superior = function(name) {
	var that = this,
		method = that[name];
	return function() {
		return method.apply(that, arguments);
	};
};
//cat基类,有自己的方法getName和speaks
var cat = function(spec) {
	var that = {};
	that.getName = function() {
		return spec.name;
	};
	that.speaks = function() {
		return spec.sound || "";
	};
	return that;
};
//子类,继承于cat,有自己的方法getName和run,通过superior调用了父类方法getName
var blackCat = function(spec) {
	spec.sound = "miao";
	var that = cat(spec), //继承cat
		superGetName = that.superior("getName"); //通过superior获得父类同名方法
	//自身的方法
	that.run = function() {
		return "this cat can run";
	};
	//自身的方法
	that.getName = function() {
		return "BlackCat's name is " + spec.name;
	};
	//换名后的父类方法
	that.superGetName = function() {
		return superGetName();
	};
	return that;
};

var myBlackCat = blackCat({
	name: "tom"
});

console.log(myBlackCat.getName());
console.log(myBlackCat.run());
console.log(myBlackCat.speaks());
console.log(myBlackCat.superGetName());
//输出:
//BlackCat's name is tom
//this cat can run
//miao
//tom

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值