Не удается получить родительский метод в javascript? [Дубликат]

Я могу понять цель функции сна, если вам приходится иметь дело с синхронным исполнением. Функции setInterval и setTimeout создают поток параллельного выполнения, который возвращает последовательность выполнения обратно в основную программу, что неэффективно, если вам нужно ждать определенного результата. Конечно, можно использовать события и обработчики, но в некоторых случаях это не то, что предназначено.

77
задан interpolack 21 June 2015 в 15:47
поделиться

13 ответов

Объект может иметь только один прототип. Наследование из двух классов может быть выполнено путем создания родительского объекта в виде комбинации двух родительских прототипов.

Синтаксис для подклассификации позволяет сделать это в декларации, поскольку правая часть extends может быть любым выражением. Таким образом, вы можете написать функцию, которая объединяет прототипы в соответствии с любыми критериями, которые вы хотите, и вызывать эту функцию в объявлении класса.

39
ответ дан Pointy 24 August 2018 в 02:04
поделиться

Нет простого способа выполнить множественное наследование класса. Я следую комбинации ассоциации и наследования для достижения такого поведения.

    class Person {
        constructor(firstname, lastname, age){
            this.firstname = firstname,
            this.lastname = lastname
            this.Age = age
        }

        fullname(){
                return this.firstname +" " + this.lastname;
            } 
    }

    class Organization {
        constructor(orgname){
            this.orgname = orgname;
        }
    }

    class Employee extends Person{
        constructor(firstname, lastname, age,id) {
            super(firstname, lastname, age);
            this.id = id;
        }

    }
    var emp = new Employee("John", "Doe", 33,12345);
    Object.assign(emp, new Organization("Innovate"));
    console.log(emp.id);
    console.log(emp.orgname);
    console.log(emp.fullname());

Надеюсь, что это будет полезно.

1
ответ дан AnandShanbhag 24 August 2018 в 02:04
поделиться

Вот потрясающий / действительно дерьмовый способ расширения нескольких классов. Я использую пару функций, которые Бабель вложил в мой перекодированный код. Функция создает новый класс, который наследует class1, а class1 наследует класс2 и т. Д. У этого есть свои проблемы, но забавная идея.

var _typeof = typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol' ? function (obj) {
  return typeof obj
} : function (obj) {
  return obj && typeof Symbol === 'function' && obj.constructor === Symbol ? 'symbol' : typeof obj
}

function _inherits (subClass, superClass) {
  if (typeof superClass !== 'function' && superClass !== null) {
    throw new TypeError('Super expression must either be null or a function, not ' + (
      typeof superClass === 'undefined' ? 'undefined' : _typeof(superClass)))
  }
  subClass.prototype = Object.create(
    superClass && superClass.prototype,
    {
      constructor: {
        value: subClass,
        enumerable: false,
        writable: true,
        configurable: true
      }
    })
  if (superClass) {
    Object.setPrototypeOf
    ? Object.setPrototypeOf(subClass, superClass)
    : subClass.__proto__ = superClass.__proto__  // eslint-disable-line no-proto
  }
}

function _m (...classes) {
  let NewSuperClass = function () {}
  let c1 = NewSuperClass
  for (let c of classes) {
    _inherits(c1, c)
    c1 = c
  }
  return NewSuperClass
}

import React from 'react'

/**
 * Adds `this.log()` to your component.
 * Log message will be prefixed with the name of the component and the time of the message.
 */
export default class LoggingComponent extends React.Component {
  log (...msgs) {
    if (__DEBUG__) {
      console.log(`[${(new Date()).toLocaleTimeString()}] [${this.constructor.name}]`, ...msgs)
    }
  }
}

export class MyBaseComponent extends _m(LoggingComponent, StupidComponent) {}
-3
ответ дан casey 24 August 2018 в 02:04
поделиться
1
ответ дан Ced 24 August 2018 в 02:04
поделиться

Реализация Серхио Карнейро и Джона требует определения функции инициализации для всех, кроме одного класса. Вот модифицированная версия функции агрегации, которая вместо этого использует конструкторы по умолчанию.

var aggregation = (baseClass, ...mixins) => {
    class base extends baseClass {
        constructor (...args) {
            super(...args);
            mixins.forEach((mixin) => {
                copyProps(this,(new mixin));
            });
        }
    }
    let copyProps = (target, source) => {  // this function copies all properties and symbols, filtering out some special ones
        Object.getOwnPropertyNames(source)
              .concat(Object.getOwnPropertySymbols(source))
              .forEach((prop) => {
                 if (!prop.match(/^(?:constructor|prototype|arguments|caller|name|bind|call|apply|toString|length)$/))
                    Object.defineProperty(target, prop, Object.getOwnPropertyDescriptor(source, prop));
               })
    }
    mixins.forEach((mixin) => { // outside contructor() to allow aggregation(A,B,C).staticFunction() to be called etc.
        copyProps(base.prototype, mixin.prototype);
        copyProps(base, mixin);
    });
    return base;
}

Вот небольшая демонстрация:

class Person{
   constructor(n){
      this.name=n;
   }
}
class Male{
   constructor(s='male'){
      this.sex=s;
   }
}
class Child{
   constructor(a=12){
      this.age=a;
   }
   tellAge(){console.log(this.name+' is '+this.age+' years old.');}
}
class Boy extends aggregation(Person,Male,Child){}
var m = new Boy('Mike');
m.tellAge(); // Mike is 12 years old.

Эта функция агрегации будет предпочитать свойства и методы класса, которые появляются позже в Список классов.

11
ответ дан Chong Lip Phang 24 August 2018 в 02:04
поделиться

Проверьте, пожалуйста, пример ниже, super работает как ожидалось. Используя несколько трюков, даже instanceof работает (большую часть времени):

// base class
class A {  
  foo() {
    console.log(`from A -> inside instance of A: ${this instanceof A}`);
  }
}

// B mixin, will need a wrapper over it to be used
const B = (B) => class extends B {
  foo() {
    if (super.foo) super.foo(); // mixins don't know who is super, guard against not having the method
    console.log(`from B -> inside instance of B: ${this instanceof B}`);
  }
};

// C mixin, will need a wrapper over it to be used
const C = (C) => class extends C {
  foo() {
    if (super.foo) super.foo(); // mixins don't know who is super, guard against not having the method
    console.log(`from C -> inside instance of C: ${this instanceof C}`);
  }
};

// D class, extends A, B and C, preserving composition and super method
class D extends C(B(A)) {  
  foo() {
    super.foo();
    console.log(`from D -> inside instance of D: ${this instanceof D}`);
  }
}

// E class, extends A and C
class E extends C(A) {
  foo() {
    super.foo();
    console.log(`from E -> inside instance of E: ${this instanceof E}`);
  }
}

// F class, extends B only
class F extends B(Object) {
  foo() {
    super.foo();
    console.log(`from F -> inside instance of F: ${this instanceof F}`);
  }
}

// G class, C wrap to be used with new decorator, pretty format
class G extends C(Object) {}

const inst1 = new D(),
      inst2 = new E(),
      inst3 = new F(),
      inst4 = new G(),
      inst5 = new (B(Object)); // instance only B, ugly format

console.log(`Test D: extends A, B, C -> outside instance of D: ${inst1 instanceof D}`);
inst1.foo();
console.log('-');
console.log(`Test E: extends A, C -> outside instance of E: ${inst2 instanceof E}`);
inst2.foo();
console.log('-');
console.log(`Test F: extends B -> outside instance of F: ${inst3 instanceof F}`);
inst3.foo();
console.log('-');
console.log(`Test G: wraper to use C alone with "new" decorator, pretty format -> outside instance of G: ${inst4 instanceof G}`);
inst4.foo();
console.log('-');
console.log(`Test B alone, ugly format "new (B(Object))" -> outside instance of B: ${inst5 instanceof B}, this one fails`);
inst5.foo();

Выведет

Test D: extends A, B, C -> outside instance of D: true
from A -> inside instance of A: true
from B -> inside instance of B: true
from C -> inside instance of C: true
from D -> inside instance of D: true
-
Test E: extends A, C -> outside instance of E: true
from A -> inside instance of A: true
from C -> inside instance of C: true
from E -> inside instance of E: true
-
Test F: extends B -> outside instance of F: true
from B -> inside instance of B: true
from F -> inside instance of F: true
-
Test G: wraper to use C alone with "new" decorator, pretty format -> outside instance of G: true
from C -> inside instance of C: true
-
Test B alone, ugly format "new (B(Object))" -> outside instance of B: false, this one fails
from B -> inside instance of B: true

Ссылка на скрипку вокруг

56
ответ дан j0k 24 August 2018 в 02:04
поделиться

использовать с пользовательской функцией для обработки множественного наследования с помощью es6

var aggregation = (baseClass, ...mixins) => {
    let base = class _Combined extends baseClass {
        constructor (...args) {
            super(...args)
            mixins.forEach((mixin) => {
                mixin.prototype.initializer.call(this)
            })
        }
    }
    let copyProps = (target, source) => {
        Object.getOwnPropertyNames(source)
            .concat(Object.getOwnPropertySymbols(source))
            .forEach((prop) => {
            if (prop.match(/^(?:constructor|prototype|arguments|caller|name|bind|call|apply|toString|length)$/))
                return
            Object.defineProperty(target, prop, Object.getOwnPropertyDescriptor(source, prop))
        })
    }
    mixins.forEach((mixin) => {
        copyProps(base.prototype, mixin.prototype)
        copyProps(base, mixin)
    })
    return base
}

class Colored {
    initializer ()     { this._color = "white" }
    get color ()       { return this._color }
    set color (v)      { this._color = v }
}

class ZCoord {
    initializer ()     { this._z = 0 }
    get z ()           { return this._z }
    set z (v)          { this._z = v }
}

class Shape {
    constructor (x, y) { this._x = x; this._y = y }
    get x ()           { return this._x }
    set x (v)          { this._x = v }
    get y ()           { return this._y }
    set y (v)          { this._y = v }
}

class Rectangle extends aggregation(Shape, Colored, ZCoord) {}

var rect = new Rectangle(7, 42)
rect.z     = 1000
rect.color = "red"
console.log(rect.x, rect.y, rect.z, rect.color)

0
ответ дан Jon 24 August 2018 в 02:04
поделиться

использовать Mixins для ES6 multiple Inheritance.

let classTwo = Base => class extends Base{
    // ClassTwo Code
};

class Example extends classTwo(ClassOne) {
    constructor() {
    }
}
1
ответ дан Liam 24 August 2018 в 02:04
поделиться

Я придумал это решение:

'use strict';

const _         = require( 'lodash' );

module.exports  = function( ParentClass ) {

    if( ! ParentClass ) ParentClass = class {};

    class AbstractClass extends ParentClass {
        /**
         * Constructor
        **/
        constructor( configs, ...args ) {
            if ( new.target === AbstractClass )
                throw new TypeError( "Cannot construct Abstract instances directly" );

            super( args );

            if( this.defaults === undefined )
                throw new TypeError( new.target.name + " must contain 'defaults' getter" );

            this.configs = configs;
        }
        /**
         * Getters / Setters
        **/
        // Getting module configs
        get configs() {
            return this._configs;
        }
        // Setting module configs
        set configs( configs ) {
            if( ! this._configs ) this._configs = _.defaultsDeep( configs, this.defaults );
        }
    }

    return AbstractClass;
}

use:

const EventEmitter  = require( 'events' );
const AbstractClass = require( './abstracts/class' )( EventEmitter );

class MyClass extends AbstractClass {
    get defaults() {
        return {
            works: true,
            minuses: [
                'u can have only 1 class as parent wich was\'t made by u',
                'every othere classes should be your\'s'
            ]
        };
    }
}

Пока вы делаете эти трюки с помощью своих классов, написанных по-своему, он может быть прикованным. но мы скоро, так как вы хотите расширить некоторую функцию / класс, написанную не так, - у вас не будет шанса продолжить цикл.

const EventEmitter  = require( 'events' );
const A = require( './abstracts/a' )(EventEmitter);
const B = require( './abstracts/b' )(A);
const C = require( './abstracts/b' )(B);

работает для меня в узле v5.4.1 с флагом -harmony

2
ответ дан Maikal 24 August 2018 в 02:04
поделиться

Это не реально, так как работает прототипическое наследование. Давайте посмотрим, как унаследованные реквизиты работают в js

var parent = {a: function() { console.log('ay'); }};
var child = Object.create(parent);
child.a() // first look in child instance, nope let's go to it's prototype
          // then look in parent, found! return the method

, давайте посмотрим, что произойдет, когда вы получите доступ к опоре, которая не существует:

child.b; // first look in child instance, nope let's go to it's prototype
         // then look in parent, nope let's go to it's prototype
         // then look in Object.prototype, nope let's go to it's prototype
         // then look at null, give up and return undefined

Вы можете использовать mixins , чтобы получить некоторые из этих функций, но вы не получите позднюю привязку:

var a = {x: '1'};
var b = {y: '2'};
var c = createWithMixin([a, b]);
c.x; // 1
c.y; // 2
b.z = 3;
c.z; // undefined

vs

var a = {x: 1}
var o = Object.create(a);
o.x; // 1
a.y = 2;
o.y; // 2
8
ответ дан qwertymk 24 August 2018 в 02:04
поделиться

На странице es6-features.org/#ClassInheritanceFromExpressions можно написать функцию агрегации, чтобы разрешить множественное наследование:

class Rectangle расширяет агрегацию ( Shape, Colored, ZCoord) {} ​​

var aggregation = (baseClass, ...mixins) => {
    let base = class _Combined extends baseClass {
        constructor (...args) {
            super(...args)
            mixins.forEach((mixin) => {
                mixin.prototype.initializer.call(this)
            })
        }
    }
    let copyProps = (target, source) => {
        Object.getOwnPropertyNames(source)
            .concat(Object.getOwnPropertySymbols(source))
            .forEach((prop) => {
            if (prop.match(/^(?:constructor|prototype|arguments|caller|name|bind|call|apply|toString|length)$/))
                return
            Object.defineProperty(target, prop, Object.getOwnPropertyDescriptor(source, prop))
        })
    }
    mixins.forEach((mixin) => {
        copyProps(base.prototype, mixin.prototype)
        copyProps(base, mixin)
    })
    return base
}

Но это уже предусмотрено в библиотеках, таких как aggregation .

2
ответ дан Sergio Carneiro 24 August 2018 в 02:04
поделиться

Джастин Фагнани описывает очень чистый (imho) способ составления нескольких классов в один, используя тот факт, что в ES2015 классы могут быть созданы с помощью выражений класса .

Выражения против деклараций

В принципе, так же, как вы можете создать функцию с выражением:

function myFunction() {}      // function declaration
var myFunction = function(){} // function expression

, вы можете сделать то же самое с классами:

class MyClass {}             // class declaration
var MyClass = class {}       // class expression

Выражение оценивается во время выполнения, когда код выполняется, тогда как объявление выполняется заранее.

Использование выражений класса для создания mixins

Вы можете использовать это для создайте функцию, которая динамически создает класс только при вызове функции:

function createClassExtending(superclass) {
  return class AwesomeClass extends superclass {
    // you class body here as usual
  }
}

Приятная вещь в том, что вы можете заранее определить весь класс и только решить, какой класс он должен распространять на время, когда вы вызываете функцию:

class A {}
class B {}
var ExtendingA = createClassExtending(A)
var ExtendingB = createClassExtending(B)

Если вы хотите объединить несколько классов вместе, поскольку классы ES6 поддерживают только одно наследование, вам необходимо создать цепочку классов, которая содержит все классы, которые вы используете муравей смешивать вместе. Итак, скажем, вы хотите создать класс C, который расширяет оба A и B, вы могли бы сделать это:

class A {}
class B extends A {}
class C extends B {}  // C extends both A and B

Проблема в том, что он очень статичен. Если вы позже решите, что хотите сделать класс D, который расширяет B, но не A, у вас есть проблема.

. Но с помощью некоторых умных обманщиков, используя тот факт, что классы могут быть выражениями, вы можете решить это, создав A и B не непосредственно как классы, а как классные заводы (с использованием функций стрелок для краткости):

class Base {} // some base class to keep the arrow functions simple
var A = (superclass) => class A extends superclass
var B = (superclass) => class B extends superclass
var C = B(A(Base))
var D = B(Base)

Обратите внимание, как мы решаем в последний момент, какие классы включать в иерархию.

Помогите нам построить будущее!

Конечно, если вы похожи на меня, это вдохновляет вас на создание окончательной библиотеки для множественного наследования в Javascript. Если вы это сделаете, пожалуйста, помогите мне сделать именно это!

mics

mics (произносится: mix) - это библиотека, которая делает множественное наследование в Javascript - легкий ветерок. Вдохновленный отличным сообщением в блоге «Реальные» миксины с Javascript-классами Джастином Фагнани, mics пытается создать минимальную библиотеку вокруг концепции использования выражений класса (фабрик) в качестве mixins. mics расширяет концепции, представленные в блоге, создавая микшинов первоклассных граждан, которые могут быть непосредственно использованы для создания объектов и могут быть смешаны с другими миксинами, а не просто с классами.

5
ответ дан Stijn de Witt 24 August 2018 в 02:04
поделиться

Это решение ES6 работало для меня:

multiple-inheritance.js

export function allOf(BaseClass, ...Mixins) {

  function copyProperties(target, source) {
    const allPropertyNames = Object.getOwnPropertyNames(source).concat(Object.getOwnPropertySymbols(source))

    allPropertyNames.forEach((propertyName) => {
      if (propertyName.match(/^(?:constructor|prototype|arguments|caller|name|bind|call|apply|toString|length)$/))
        return
      Object.defineProperty(target, propertyName, Object.getOwnPropertyDescriptor(source, propertyName))
    })
  }

  class Base extends BaseClass
  {
    constructor (...args) {
      super(...args)

      Mixins.forEach((Mixin) => {
        copyProperties(this, new Mixin(...args))
      })
    }
  }

  Mixins.forEach((mixin) => {
    copyProperties(Base.prototype, Mixin.prototype)
  })

  return Base
}

main.js

import { allOf } from "./multiple-inheritance.js"

class A
{
    constructor(name) {
        this.name = name
    }
    sayA() {
        return this.name
    }
}

class B
{
    constructor(name) {
        this.name = name
    }
    sayB() {
        return this.name
    }
}

class AB extends allOf(A, B)
{
    sayAB() {
        return this.name
    }
}

const ab = new AB("ab")
console.log("ab.sayA() = "+ab.sayA()+", ab.sayB() = "+ab.sayB()+", ab.sayAB() = "+ab.sayAB())

Урожайность на консоли браузера :

ab.sayA() = ab, ab.sayB() = ab, ab.sayAB() = ab
1
ответ дан user2006754 24 August 2018 в 02:04
поделиться
Другие вопросы по тегам:

Похожие вопросы: