Подтвердить что ты не робот

Может ли JavaScript-конструктор возвратить функцию и сохранить наследование?

function F() {
    return function() {
        return {};
    }
}

var f = new F();
f instanceof F; // returns false

Насколько я понимаю, если я хочу, чтобы instanceof работал, мне нужно вернуть this из конструктора. Но я хочу, чтобы конструктор возвращал функцию, и я не могу назначить this.

Итак, это действительно невозможно или может быть сделано каким-то образом, для f = new F() для возврата функции и еще f instanceof F для возврата true?

4b9b3361

Ответ 1

function F() {
    var r = function() {
        return {};
    };

    r.__proto__ = this.__proto__;
    return r;
}

var f = new F();
f instanceof F;
true
f();
Object

Работает только в браузерах с __proto__

Ответ 2

Конечно, вы можете сделать все функции instanceof F, установив F.prototype = Function.prototype;.

К сожалению, похоже, что ECMAScript не позволяет создавать подкласс функций.

Однако вы можете сделать это в Gecko, используя устаревшее свойство __proto__:

function F() {
    function f() {
        return {};
    }
    f.__proto__ = F.prototype;
    return f;
 }
 F.prototype.__proto__ = F.__proto__;

Ответ 3

Для всех, кто сегодня сталкивается с этим, с ES6/2015 появляется новый синтаксис, который вы можете использовать, чтобы избежать устаревшего свойства __proto__; Object.setPrototypeOf. Обратите внимание, что MDN предупреждает, что это медленная/дорогая операция.

function F() {
    const f = function() {
        return {};
    }
    Object.setPrototypeOf(f, F.prototype);
    return f;
}

var f = new F();
f instanceof F; // returns true
f(); // returns {}

Заметьте также, что это немного странно, если вы хотите инициализировать значения в конструкторе. Вам нужно установить их в качестве реквизита для функции, которую вы вернете, но последующие дополнения к прототипу будут ссылаться на них как на 'this'. например.

function F() {
    const f = function() {
        return {};
    }
    f.favoriteBand = 'The Books';
    Object.setPrototypeOf(f, F.prototype);
    return f;
}
F.prototype.getFavoriteBand = function(){ return this.favoriteBand; }

var f = new F();
f.getFavoriteBand() // returns 'The Books'

Ответ 4

В вашем примере F не является конструктором, это функция, которая возвращает анонимный конструктор, который вы затем вызываете new. instanceof работает, просматривая цепочку прототипов, поэтому ваш код не работает, потому что вы неправильно настроили прототипы.

Этот page имеет хорошее объяснение конструкторов JavaScript и как подкласс.

Взгляните на следующий код и посмотрите, помогает ли он.

function F() {
    this.whoami = 'F';
    this.whatami = 'F';

}

function Sub() {
 this.whoami = 'G';
}

Sub.prototype = new F();

function G() {
    return new Sub;
}

var f = new G();
console.log(f instanceof F); // returns false
console.log(f.whoami);
console.log(f.whatami);
​