使用函数继承时相当于“实例”

What would be the equivalent of `instanceof` when using functional inheritance?

本文关键字:实例 相当于 函数 继承      更新时间:2023-09-26

在 JavaScript 中,有一种实现继承的模式称为"函数继承",在 Crockfords 的第 5 章"JavaScript:好部分"中描述。

与使用伪经典模式相比,该模式的缺点之一是我们失去了使用 instanceof 运算符区分类型的能力。

有什么方法可以实现相同的目标吗?我们如何知道两个对象在某种程度上是相关的,因为它们具有相同的父/基"类型"?

另外,即使他们是同一类型的后代,我们怎么知道他们自己是不同的类型?

我不知道不能使用instanceof是否是一个很大的损失,但似乎并非如此。

笔记

对于那些不熟悉Crockford解释的人,你可以在以下位置看到一个例子:JSFiddle,从这里开始。

instanceof运算符并不特殊。您可以按照 Mozilla 开发者网络上的说明自行实现它。有关更多详细信息,请参阅以下问题的已接受答案:

JavaScript 继承和构造函数属性

以下是如何在 JavaScript 中实现instanceof运算符:

function instanceOf(object, constructor) {
    while (object != null) {
        if (object == constructor.prototype) { //object is instanceof constructor
            return true;
        } else if (typeof object == 'xml') { //workaround for XML objects
            return constructor.prototype == XML.prototype;
        }
        object = object.__proto__; //traverse the prototype chain
    }
    return false; //object is not instanceof constructor
}

想要实现功能继承的instanceOf?这也很容易做到:

var object = child({ name: "a functional object" });
alert(object.instanceOf(child)); // true
alert(object.instanceOf(base));  // true
alert(object.sayHello());        // Hello, I'm a functional object
function base(spec) {
    var that = {};
    that.name = spec.name;
    that.constructors = [base];
    that.instanceOf = instanceOf;
    return that;
}
function child(spec) {
    var that = base(spec);
    that.sayHello = sayHello;
    that.constructors.push(child);
    return that;
    function sayHello() {
        return "Hello, I'm " + this.name;
    }
}
function instanceOf(constructor) {
     return this.constructors.indexOf(constructor) >= 0;
}

当然,在真正的函数式编程中,根本不需要使用instanceof

所以想象一下我们有这些:

mammal { giveBirth }
reptile { layEgg }
cat : mammal { purr, playWithChildren }
dog : mammal { bark }
lion : mammal { purr }

(cat继承mammal并实现purr()等...

现在想象一下你有一系列动物。

我想你在问的是我们如何判断animals[0]是否是cat

想知道animals[0]是否是一种cat的愿望来自我们知道猫可以做某些事情的事实。我们不知道animals[0]是否是cat,我们真正想知道的是animals[0]会发出呼噜声。也许animals[0].purr !== undefined比知道它是否是cat更准确.这确实意味着我们需要检查每个函数,而不是我们知道实现多个函数的猫的容器概念,但它使实现更加健壮和面向未来(考虑一下我们是否只关心咕噜声和狮子被添加到动物类型后面(。

至于关于继承的问题,我建议我们不需要知道动物是否是mammal我们需要知道它们是否giveBirth。这将再次确保我们的实现更具前瞻性,以便当我们稍后添加marsupial时,我们关于分娩而不是产卵的所有逻辑仍然成立。

将父对象存储在对象中,然后

if (obj1.parentObject == obj2.parentObject) {//Do your things}

在"函数继承"("JavaScript:好的部分"(中没有inctanceof的某些类型和区别。
它是关于匿名函数之间的交换和关系,匿名函数通常生成具有私有功能的对象。
这些函数的逻辑层次结构是使用条件首选项设置的。
该函数可以相互调用,扩展"父"对象方法,扩展其功能。
例如,在"功能继承"中,创建一个称为"哺乳动物"的新类型,如下所示:

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

通过一些条件协议,我们可以接受它作为父类型(类(。
现在我们可以创建另一个匿名函数,它将负责"哺乳动物"类型(类(的子类型(子类(。此函数将调用"parent"函数mammal()以获取具有基本功能的对象:

var cat = function (spec) { 
    spec.saying = spec.saying || 'meow'; 
    var that = mammal(spec); 
    that.purr = function (n) { 
        var i, s = ''; 
        for (i = 9; i < n; i += 1) { 
            if (s) { 
               s += 
            } 
            s += 'r'; 
        } 
        return s; 
    }; 
    that.get_name = function () { 
        return that.says() + ' ' + spec.name + ' ' + that.says(); 
    }; 
    return that; 
}; 
var myCat = cat({name: 'Henrietta'});