通过伪经典实例化 (JavaScript) 掌握原型继承

Posted

技术标签:

【中文标题】通过伪经典实例化 (JavaScript) 掌握原型继承【英文标题】:Grasping prototypical Inheritance through pseudoclassical instantiation (JavaScript) 【发布时间】:2016-04-10 07:31:00 【问题描述】:

我正在尝试通过 javascript 使用继承来通过测试套件。以下是我到目前为止的代码的 sn-p:

var Infant = function() 
    this.age  = 0;
    this.color = 'pink';
    this.food = 'milk';

;
Infant.prototype.eat = function()
    return this.eat;



var Adolescent = function() 

    this.age = 5;
    this.height = 'short';
    this.job = 'keep on growing';

;

我想从 Infant 类和 eat 方法继承 food 属性,但我的尝试失败了。我最初的想法是分配 this.Adolescent = Infant.food;但这没有用。我知道我需要将 Infant 设置为 Superclass,但我正在旋转我的***

【问题讨论】:

【参考方案1】:

在 JavaScript 中使用构造函数进行继承时,您:

    将“派生”构造函数的prototype 属性设为其原型是“基”构造函数的prototype 属性的对象。

    将“派生”构造函数的prototype 属性上的constructor 属性设置为指向“派生”构造函数。

    使用正确的this 从“派生”构造函数调用“基”构造函数。

像这样:

var Infant = function() 
    this.age  = 0;
    this.color = 'pink';
    this.food = 'milk';
;
Infant.prototype.eat = function()
    return /*...something...*/; // Returning `this.eat` doesn't make any sense, that's the function we're in
;

var Adolescent = function() 

    // #3 Give super a chance to initialize the instance, you can pass args if appropriate
    Infant.call(this);

    this.age = 5;
    this.height = 'short';
    this.job = 'keep on growing';
;

// Set up Adolescent's prototype, which uses Infant's prototype property as its prototype
Adolescent.prototype = Object.create(Infant.prototype);     // #1
Object.defineProperty(Adolescent.prototype, "constructor",  // #2
    value: Adolescent,
    writable: true,
    configurable: true
);
// (In pre-ES5 environments that don't event have `Object.defineProperty`, you'd use
// an assignment instead: `Adolescent.prototype.constructor = Adolescent;`

Object.create 是在 ES5 中添加的,因此它不会出现在过时的 JavaScript 引擎上,比如 IE8 中的引擎。不过,上面使用的单参数版本可以是easily shimmed。

在 ES2015 中,我们可以选择使用新的 class 语义:

class Infant 
    constructor() 
        this.age  = 0;
        this.color = 'pink';
        this.food = 'milk';
    

    eat() 
        return /*...something...*/;
    


class Adolescent extends Infant             // extends does #1 and #2
    constructor() 
        super();                             // #3, you can pass args here if appropriate

        this.age = 5;
        this.height = 'short';
        this.job = 'keep on growing';
    

【讨论】:

轰隆隆!很好的答案! 非常感谢!由于我最初的编码知识是在 Java 中的,因此我更习惯于类语义。 @DLF85:乐于助人。请注意,原型继承与 Java 等基于类的继承完全不同;上面的语义主要是语法糖,不管语法如何,它仍然是原型继承。 JS 非常灵活,它几乎可以模仿基于类的继承,但请注意关键区别在于确实涉及到单独的对象(而在 Java 中,它是一个同时具有基类和派生类特征的对象)。当然,您不仅限于对象的“类”;您可以一次性进行继承,这非常方便。 还要注意新的类语义是全新的。如果你想在野外使用它们,你必须使用一个转译器(其中有几个;我使用(但不隶属于)Babel。 看来我还是一头雾水。我现在正在尝试通过类外的方法将 +1 添加到构造函数类中的值,但控制台一直告诉我我的方法不是函数。我觉得这可能与this 有关。类内的一切运行良好,似乎方法是undefined/not a function

以上是关于通过伪经典实例化 (JavaScript) 掌握原型继承的主要内容,如果未能解决你的问题,请参考以下文章

如何在 JavaScript 中从字符串实例化一个类

javascript 伪经典类

深入理解脚本化CSS系列第六篇——脚本化伪元素的6种方法

javascript原型继承

JavaScript 实现的checkbox经典实例分享

接口与抽象类的应用(包括各自设计模式)