繁体   English   中英

基于Crockford的函数继承在Javascript中使用超级方法

[英]Using super methods in Javascript based on Crockford's functional inheritance

我一直在阅读Crockford的“ The Good Parts”中有关函数继承的章节。 在哺乳动物的示例中,对于他为什么使用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来复制相同的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');

使super_get_name成为一个函数-每次调用时-都会调用that方法的原始 get_name方法。 这允许新的 get_name调用旧的 (超类) get_name

现在,如果原始的get_name方法除了返回一个永远不变的值之外,将永远不会有任何其他效果,那么,是的,这毫无意义; 您可以只保存该单值永不更改,然后在新的get_name使用它。 但是,如果原始的get_name实际上可以执行操作(例如,运行AJAX请求或更改HTML元素的样式),或者其返回值可以更改(例如,是否有一些对应的set_name方法),那么您的代码做什么(保存原始返回值并使用它)和Crockford的代码做什么(保存原始方法并调用它)之间将存在重要的区别。

Crockford在本书的这一章中引起了困惑,因为Crockford所描述的是“他的”在JavaScript中实现继承的首选模式,这取决于他用Function.prototype.method (第1.3章)扩展的Function对象,向Function对象添加方法。

coolcat示例中解决的问题是需要访问父类型的方法。 在像Java这样的“经典” OO语言中,这很自然,因为类本身就存在。 在JavaScript继承是典型的情况下,您将创建一个mammal类型的对象,然后修改该对象以创建类型catcoolcat

根据您的设计,您可以添加属性和功能或覆盖“继承的”功能。 当您覆盖“继承的”函数时,就会出现问题,在JavaScript中,您基本上用新函数替换了旧函数,从而失去了旧函数。

克罗克福德现在需要做两件事:

  1. 获取父(猫)的get_name方法;
  2. 以一种可以从覆盖方法中使用的方式保存它。

在此代码中:

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;
};

他通过调用高级方法来获得一个函数,该函数获得了猫的get_name函数。 然后他通过将其保存到coolcat函数(/ object)中的super_get_name变量中来进行操作,从而允许在猫被其猫的get_name函数覆盖(更正确地覆盖)之前访问该猫的get_name函数。

我认为之所以会引起混淆,是因为:

  1. superior方法的名称很奇怪:“ superior”方法只是按名称查找函数 ,可以更好地命名,例如,将其命名为getFunctionByName (您可以通过将字符串get_name替换为purr来尝试,coolcat的get_name现在会调用purr,只需记住将其称为super_get_name(10)否则将返回一个空字符串)。
  2. 其次,代码和模式依赖于某些特定的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的好部分”的演讲。 演讲绝对精彩,比这本书好得多。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM