对象不继承原型函数 [英] Objects don't inherit prototyped functions

查看:82
本文介绍了对象不继承原型函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个构造函数,它充当超类:

I have one constructor function, which acts as a superclass:

Bla = function(a){this.a = a;}

我将其原型化为包含一个简单的方法:

I prototype it to include a simple method:

Bla.prototype.f = function(){console.log("f");

现在新 Bla(1).f(); 将在控制台中记录f。但是,让我说我需要一个继承自Bla的子类:

And now new Bla(1).f(); will log "f" in the console. But, lets say that I need a subclass that inherits from Bla:

Bla2 = function(a)
{
    this.base = Bla;
    this.base();
}

x = new Bla2(5);

现在,按预期, xa 给了我 5 。但是, x.f undefined !好像 Bla2 没有从 Bla 类继承它!为什么会发生这种情况?如何更正?

Now, as expected, x.a gives me 5. But, x.f is undefined! Seems like Bla2 didn't inherit it from the Bla class! Why is this happening and how do I correct it?

推荐答案


似乎 Bla2 没有从 Bla 类继承它!

对。你没有做任何事情来连接那里的继承,你刚刚创建了一个 Bla2 的成员,名为 base 是一个 Bla 实例。 base 不是JavaScript中的特殊标识符。

Right. You haven't done anything to hook up inheritance there, you've just created a member of Bla2 called base which is a Bla instance. base is not a special identifier in JavaScript.

在JavaScript中设置继承的典型方法如下所示:

The typical way to set up inheritance in JavaScript looks like this:

// The base constructor function
function Base(x) {
    // Base per-instance init
    this.x = x;
}

// An example Base function
Base.prototype.foo = function() {
    console.log("I'm Base#foo, x = " + this.x);
};

// The Derived constructor function
function Derived(x, y) {
    // Normally you need to call `Base` as it may have per-instance
    // initialization it needs to do. You need to do it such that
    // within the call, `this` refers to the current `this`, so you
    // use `Function#call` or `Function#apply` as appropriate.
    Base.call(this, x);

    // Derived per-instance init
    this.y = y;
}

// Make the Derived.prototype be a new object backed up by the
// Base.prototype.    
Derived.prototype = Object.create(Base.prototype);

// Fix up the 'constructor' property
Derived.prototype.constructor = Derived;

// Add any Derived functions
Derived.prototype.bar = function() {
    console.log("I'm Derived#bar, x = " + this.x + ", y = " + this.y);
};

...其中 Object.create 来自ES5,但它是可以很容易地大部分填充的东西之一。 (或者你可以使用一个只做最低限度而不试图完成所有 Object.create 的函数;见下文。)然后你使用它:

...where Object.create is from ES5, but it's one of the things that can easily be mostly shimmed. (Or you can use a function that only does the bare minimum without trying to do all of Object.create; see below.) And then you use it:

var d = new Derived(4, 2);
d.foo(); // "I'm Base#foo, x = 4"
d.bar(); // "I'm Derived#bar, x = 4, y = 2"

实例 | 来源

在旧代码中,您有时会看到派生.prototype 设置如下:

In older code you sometimes see the Derived.prototype set up like this instead:

Derived.prototype = new Base();

...但这样做有问题: Base 可以进行每个实例的初始化,这不适合继承的 Derived 的全部内容。它甚至可能需要参数(因为我们的 Base 会这样做;我们将为 x 传递什么?)。通过改为使 Derived.prototype 成为由 Base.prototype 支持的新对象,我们得到正确的东西。然后我们从 Derived 中调用 Base 来获取每个实例的初始化。

...but there's a problem with doing it that way: Base may do per-instance initialization which isn't appropriate for the entirety of Derived to inherit. It may even require arguments (as our Base does; what would we pass for x?). By instead making Derived.prototype just be a new object backed by the Base.prototype, we get the correct stuff. Then we call Base from within Derived to get per-instance init.

以上是非常基本的,你可以看到涉及许多步骤。它也很少或根本没有使超级调用变得容易和高度可维护。这就是你看到那么多继承脚本的原因,比如Prototype的 Class ,Dean Edwards的Base2,或(cough)我自己的 Lineage

The above is very basic and as you can see involves a number of steps. It also does little or nothing to make "supercalls" easy and highly-maintainable. That's why you see so many "inheritance" scripts out there, like Prototype's Class, Dean Edwards' Base2, or (cough) my own Lineage.

如果您不能依赖环境中的ES5功能,并且不希望包含一个基于 Object.create的基础知识的垫片,您可以在其位置使用此功能:

If you can't rely on having ES5 features in your environment, and don't want to include a shim that does the basics of Object.create, you can just use this function in its place:

function simpleCreate(proto) {
    function Ctor() {
    }
    ctor.prototype = proto;
    return new Ctor();
}

然后代替

Derived.prototype = Object.create(Base.prototype);

你要这样做:

Derived.prototype = simpleCreate(Base.prototype);

当然,你可以做更多事情来自动挂钩事情 —全部 Lineage 基本上都是。

Of course, you can do more to automate hooking things up — which is all Lineage basically does.

......最后:上面我简单地使用了匿名函数,例如:

...and finally: Above I've used anonymous functions for simplicity, e.g.:

Base.prototype.foo = function() {
    // ...
};

...但我在实际代码中没有这样做,因为我想帮助我的工具帮助我。所以我倾向于在每个类(构造函数和相关原型)周围使用模块模式并使用函数声明(因为我在网上工作,而IE7和IE8 仍然有问题的命名函数表达式。所以,如果我没有使用 Lineage ,我会像这样做:

...but I don't do that in my real code, because I like to help my tools help me. So I tend to use the module pattern around each "class" (constructor function and associated prototype) and use function declarations (since I do work for the web, and IE7 and IE8 still have problems with named function expressions. So if I weren't using Lineage, I'd do the above like this:

// Base
(function(target) {
    // Base constructor
    target.Base = Base;
    function Base(x) {
        // Base per-instance init
        this.x = x;
    }

    // An example Base function
    Base.prototype.foo = Base$foo;
    function Base$foo() {
        console.log("I'm Base#foo, x = " + this.x);
    }
})(window);

// Derived
(function(target, base) {
    // The Derived constructor function
    target.Derived = Derived;
    function Derived(x, y) {
        // Init base
        base.call(this, x);

        // Derived per-instance init
        this.y = y;
    }

    // Make the Derived.prototype be a new object backed up by the
    // Base.prototype.    
    Derived.prototype = Object.create(base.prototype);

    // Fix up the 'constructor' property
    Derived.prototype.constructor = Derived;

    // Add any Derived functions
    Derived.prototype.bar = Derived$bar;
    function Derived$bar() {
        console.log("I'm Derived#bar, x = " + this.x + ", y = " + this.y);
    }
})(window, Base);

......或类似的东西。 实时副本 | 来源

...or something like that. Live copy | source

这篇关于对象不继承原型函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆