JavaScript实现函数式继承
在『JavaScript实现原型继承』和『JavaScript实现类的继承』 中介绍了两种JavaScript实现面向对象中继承机制的方式。 本文介绍在JavaScript中更加优雅的继承方式:函数是继承。 利用JavaScript的闭包现象完美地解决了信息隐藏的问题, 也提供了访问父类对象的机制。
对象封装
首先我们需要提供一种封装对象的方式,支持私有的属性/方法,以及公有属性/方法。 既然是函数式编程,那就用一个函数来创建对象。 后面将会看到,JavaScript的函数非常擅长这件事情。
var constructor = function(args){
// 私有属性、私有方法
var private_property;
function private_method(){}
// 创建新对象
var obj = {description: 'a new object'};
// 公有属性、公有方法
obj.public_property = 'xxx';
obj.public_method = function(){};
return obj;
};
私有属性
这里我们通过闭包变量来存放私有属性,闭包函数来存储私有方法。
由于JavaScript的函数作用域,它们在constructor
外部完全不可见,而在obj
的创建和自定义过程中完全可见。
公有属性
为obj
添加的公有属性则在constructor
外部可以通过obj.public_property
访问。
对象继承
只需要在对象封装的代码上稍作改动便可实现对象继承,同时可以支持对super
的访问。
下面我们将看到JavaScript函数极具灵活性。
一个例子
在『创建新对象』时,我们调用另一个constructor
即可完成对象继承。例如:
var make_person = function(args){
// 这些是私有的
var hobbies, age;
// 创建一个对象
var person = {
name: args.name,
greet: function(){
console.log('Hi, I am ' + this.name);
}
};
return person;
}
var make_man = function(args){
// 这些是私有的
var girl, property;
// 创建一个父级对象
var man = make_person(args);
// 自定义
man.talk = function(){}
return man;
}
访问super
函数式的对象继承还有另外一个好处:我们可以控制父级对象的创建过程,
并且访问super
属性,即使它们被同名属性所隐藏。
例如在man
中访问person
的greet
方法:
var make_man = function(args){
var man = make_person(args),
super_greet = man.greet.bind(man);
man.greet = function(){
super_greet();
console.log('And I am a man.');
}
return man;
}
把greet
函数绑定到man
是必要的,否则super_greet
中的this
将会绑定到global
。
是为了为了简化这一过程,可以定义一个工具函数:
Object.method('super', function(name){
var method = this[name];
return function(){
return method.apply(this, arguments);
};
});
然后重新实现make_man
:
var make_man = function(args){
var man = make_person(args),
super_greet = man.super('greet');
man.greet = function(){
super_greet();
console.log('And I am a man.');
}
return man;
}
本文采用 知识共享署名 4.0 国际许可协议(CC-BY 4.0)进行许可,转载注明来源即可: https://harttle.land/2016/02/25/javascript-functional-inheritance.html。如有疏漏、谬误、侵权请通过评论或 邮件 指出。