在基于Crockford's的功能继承
Using super methods in Javascript based on Crockford's functional inheritance
我一直在阅读Crockford的《好的部分》中关于函数继承的章节。在他给出的哺乳动物例子中,我有点困惑他为什么使用superior
方法来修改get_name
函数。以下是有问题的例子:
Function.prototype.method = function (name, func) {
this.prototype[name] = func;
return this;
};
var mammal = function (spec) {
var that = {};
that.get_name = function () {
return spec.name;
};
that.says = function () {
return spec.saying || '';
};
return that;
};
var myMammal = mammal({
name: 'Herb'
});
var cat = function (spec) {
spec.saying = spec.saying || 'meow';
var that = mammal(spec);
that.purr = function (n) {
var i, s = '';
for (i = 0; i < n; i += 1) {
if (s) {
s += '-';
}
s += 'r';
}
return s;
};
that.get_name = function () {
return that.says() + ' ' + spec.name + ' ' + that.says();
};
return that;
};
Object.method('superior', function (name) {
var that = this,
method = that[name];
return function () {
return method.apply(that, arguments);
};
});
var coolcat = function (spec) {
var that = cat(spec);
var super_get_name = that.superior('get_name');
that.get_name = function (n) {
return 'like ' + super_get_name() + ' baby';
};
return that;
};
var myCoolCat = coolcat({
name: 'Bix'
});
var name = myCoolCat.get_name(); // 'like meow Bix meow baby'
我对此感到困惑,因为我可以通过删除superior
方法并按如下方式更改coolcat
来复制相同的东西:
var coolcat = function(spec) {
var that = cat(spec);
var super_get_name = that.get_name();
that.get_name = function(n) {
return 'like ' + super_get_name + ' baby';
};
return that;
};
所以,我不明白Crockford为什么选择使用superior
方法。有人能解释吗?
这里的想法是:
var super_get_name = that.superior('get_name');
使CCD_ 6成为一个函数;每次调用时;调用that
的原始get_name
方法。这允许新get_name
调用旧(超类)get_name
。
现在,如果最初的get_name
方法除了返回一个永远不变的值之外,永远不会有任何效果,那么是的,这有点毫无意义;您可以只保存一个从未更改的值,然后在新的get_name
中使用它。但是,如果原始的get_name
实际上可以做一些事情(例如,运行AJAX请求,或更改HTML元素的样式),或者如果它的返回值可以更改(例如,如果有一些相应的set_name
方法),那么代码所做的(保存原始返回值并使用它)和Crockford的代码所做(保存原始方法并调用它)之间会有一个重要的区别。
Crockford书的这一章引起的困惑是,Crockford所描述的是"他"在JavaScript中实现继承的首选模式,该模式依赖于他用Function.prototype.method
扩展Function
对象(第1.3章),他使用CCD_16向Function对象添加方法。
coolcat
示例中解决的问题是需要访问父类型的方法。在Java这样的"经典"OO语言中,这是很自然的,因为类本身就存在。在JavaScript继承是原型的情况下,您创建一个类型为mammal
的对象,然后修改该对象以创建类型为CCD19或coolcat
。
根据您的设计,您可以添加属性和函数或覆盖"继承"的函数。当您重写"继承的"函数时,问题就会出现,在JavaScript中,您基本上用新函数替换旧函数,从而丢失旧函数。
克罗克福德现在需要做两件事:
- 得到父母(猫)的
get_name
方法;以及 - 以可在重写方法中使用的方式保存它
在此代码中:
var coolcat = function(spec) {
var that = cat(spec),
super_get_name = that.superior('get_name');
that.get_name = function(n) {
return 'like ' + super_get_name() + ' baby';
};
return that;
};
他做了1。通过调用superior方法得到一个得到cat的CCD_ 22函数的函数;他做了2。通过将其保存到coolcat函数(/object)内的CCD_ 23变量,允许在被coolcat的get_name
函数覆盖(更正确地覆盖)之前访问cat的get_name
函数。
在我看来,出现这种混乱是因为:
superior
方法的名称很奇怪:"superior"方法只是一个按名称查找的函数方法,可以更好地命名为getFunctionByName
(您可以通过将字符串get_name
替换为purr
来尝试此操作,coolcat的get_name现在将调用purr,只需记住将其调用为super_get_name(10)
,否则您将得到一个空字符串)- 其次,代码和模式通过依赖一些特定的Crockford模式来混淆代码,如果你试图在没有阅读整本书的情况下深入本章,可能会给你带来压力
我认为有一种更简单的方法可以实现这一点,我认为因为它是完全本地化的,所以更容易理解等等,如下面的代码所示:
var coolcat = function(spec) {
var that = cat(spec);
that.parent_get_name = that.get_name;
that.get_name = function() {
return 'like ' + this.parent_get_name() + ' baby';
};
return that;
};
还有一些其他奇怪的地方,例如coolcat get_name
函数定义中的参数n
,我只能假设它来自于复制purr函数,这将暗示一个幽灵写入器!
最后,我建议大家在读这本书之前,应该听听他关于"JavaScript的好部分"的演讲。这篇演讲非常精彩,比这本书好多了。
- 添加文字和评论功能更新Div
- JavaScript打印功能使日历停止工作
- 每当您在选择器内移动鼠标时,悬停功能就会重复
- 如何防止网页加载后自动启动功能
- 除修剪外的其他功能
- 悬停功能触发器
- 使用angularjs向浏览器发送servlet响应(下载功能)
- 删除CKEditor工具栏按钮,但不删除功能
- 异步facebook功能
- 如何将chrome扩展功能移植到移动设备(特别是jquery和trello)
- 从控制器继承了隔离的作用域以生成可重用的指令
- Javascript-经理是一个人,但不是经理本身?功能/原型继承
- KnockoutJS 通过 ko.utils.extend 继承功能
- 功能继承
- 农业网格继承功能
- 在基于Crockford's的功能继承
- 组合优于继承,这是向视图添加额外功能而不诉诸继承的更好方式
- Javascript继承具有父级父级的功能
- Javascript继承:用模块模式和$.extend覆盖功能
- 是否有一种方法可以访问从基本模块继承的dojo功能