JavaScript继承和提升 [英] JavaScript Inheritance and Hoisting

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

问题描述

在当前的Web项目中,我正在使用多个JavaScript文件,每个文件都包含从其他类型继承的类型定义.所以在任何给定的文件中,我都可能有类似...

In my current web project, I'm working with multiple JavaScript files, each containing type definitions that inherit from other types. So in any given file, I could have something like ...

function Type(){
    ParentType.call(this);
}
Type.prototype = Object.create( ParentType.prototype );
Type.prototype.constructor = Type;

...,而ParentType在另一个文件中的声明与此类似:

... with the ParentType declared similarly in another file:

function ParentType(){
    this.data = "";    
}    

由于在<head>标记中处理许多JavaScript文件变得很麻烦,因此我编写了一个bash脚本将这些文件连接成一个文件(称为master.js).这样,我可以在HTML中链接单个文件.

Since working with many JavaScript files becomes bothersome in the <head> tag, I wrote a bash script to concatenate the files into a single file (called master.js). That way, I can link a single file in my HTML.

对于只有一个孩子的类型,无论我的文件串联的顺序如何,原型链都是正确构建的.换句话说,这个片段...

For types that have only a single child, the prototype chain is built correctly, regardless of the order of concatenation of my files. In other words, this snippet ...

function ParentType(){
    this.data = "";
}

function Type(){
    ParentType.call(this);
}
Type.prototype = Object.create( ParentType.prototype );
Type.prototype.constructor = Type;

...的行为与此代码段相同:

... acts identical to this snippet:

function Type(){
    ParentType.call(this);
}
Type.prototype = Object.create( ParentType.prototype );
Type.prototype.constructor = Type;

function ParentType(){
    this.data = "";
}

在任何一种情况下创建Type的实例时,ParentType.prototype.isPrototypeOf(typeobj)都返回true(其中typeobj是我的Type实例).

When I create an instance of Type in either scenario, ParentType.prototype.isPrototypeOf(typeobj) returns true (where typeobj is my instance of Type).

但是,当我在原型链"的末尾添加其他类型时,它仅在文件按顺序串联时才有效,即:

However, when I add another type to the end of the "prototype chain", it only works when the files are concatenated in order, i.e.:

function ParentType(){
    this.data = "";
}

function Type(){
    ParentType.call(this);
}
Type.prototype = Object.create( ParentType.prototype );
Type.prototype.constructor = Type;

function ChildType(){
    Type.call(this);
}
ChildType.prototype = Object.create( Type.prototype );
ChildType.prototype.constructor = ChildType;

...,否则,链断开".我对为什么在单子场景中可以这样做的猜测是因为两个类型定义都被悬挂,并且只有一组声明可以担心原型链.但是对于多链接原型链,如果语句混乱,则该链将无法正确连接.

... and otherwise, the chain "breaks". My guess as to why this is okay in a single-child scenario is because both type definitions get hoisted, and there is only one set of statements to worry about regarding the prototype chain. But for multi-link prototype chains, if the statements are out of order, the chain fails to connect properly.

所以我真正要问的是,有没有一种方法可以在JavaScript中实现工作"的继承,而不管文件的连接顺序如何?我的第一个虽然是extends的处理方式,但是后来我了解到,即使class定义也没有得到遵守!

注意:工作"是指子类型从(所有)父对象继承函数/值,并且isPrototypeOf在通过其父对象的任何原型进行检查时,对于任何对象均返回true.

So what I'm really asking is, is there a way to implement inheritance in JavaScript that "works" regardless of the order in which my files are concatenated? My first though was the class and extends way of doing things, but then I learned that even class definitions aren't hoisted!

Note: by "works", all I mean is that subtypes inherit functions/values from (all of) their parents, and isPrototypeOf returns true for any object when checked against any of its parents' prototypes.

推荐答案

对于多链接原型链,如果语句混乱,则链无法正确连接.

For multi-link prototype chains, if the statements are out of order, the chain fails to connect properly.

是的.您需要先设置Type.prototype,然后才能使用它创建ChildType.prototype.这与提升函数声明无关.

Yes. You need to set Type.prototype before using it to create ChildType.prototype. This doesn't have to do anything with the hoisting of the function declarations.

是否有一种方法可以在JavaScript中实现起作用"的继承,而与文件的连接顺序无关?

Is there a way to implement inheritance in JavaScript that "works" regardless of the order in which my files are concatenated?

好吧,您可以可以使用 Object.setPrototypeOf :

Well, you can might use Object.setPrototypeOf:

function ChildType(){
    Type.call(this);
}
Object.setPrototypeOf(ChildType.prototype, Type.prototype);

function Type(){
    ParentType.call(this);
}
Object.setPrototypeOf(Type.prototype, ParentType.prototype);

function ParentType(){
    this.data = "";
}

但是,您确实真的想避免使用该方法,而像这样依靠吊装是非常糟糕的做法,因此,您确实应该修复串联脚本以使用正确的顺序.或使用可以为您解决依赖性的模块系统.

However, you really really want to avoid that method, and relying on hoisting like this is a very bad practice, so you really should fix your concatenation script to use the correct order. Or use a module system that figures dependencies out for you.

我的第一个方法是classextends,但是后来我了解到甚至没有class定义!

My first though was the class and extends way of doing things, but then I learned that even class definitions aren't hoisted!

这是一件好事.只需将它们视为纯糖-您始终需要按照层次结构以正确的顺序进行设置.

That's a good thing. Just consider them to be purely sugar - you always need to set them up in the correct order, following the hierarchy.

这篇关于JavaScript继承和提升的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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