/*
当一个函数对象被创建时,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
《JavaScript语言精粹》--第5章:继承
最新推荐文章于 2021-11-22 16:54:52 发布