2015-03-09 2 views
2

Я хочу написать функцию для настройки цепи прототипа, но я хочу, чтобы не использовать __proto__ напрямую или Object.setPrototypeOf. Это можно сделать? Если нет, то предпочтительнее ли вы от персистентности производительности?Конфигурирование цепочки [[Prototype]] без __proto__

Кроме того, правильно ли это описывать как реализацию mixins?

Это то, что у меня есть (использует __proto__):

function mix(fn) { 

    var ancestorFns, curr 

    if (typeof fn !== 'function') { 
     throw 'fn must be a function.'; 
    } 

    ancestorFns = Array.prototype.slice.call(arguments, 1); 
    curr = fn.prototype; 

    ancestorFns.forEach(function(ancestorFn) { 

     if (typeof ancestorFn !== 'function') { 
      throw 'ancestorFn must be a function.'; 
     } 

     curr = curr.__proto__ = ancestorFn.prototype; 

    });  

} 

Использование:

function Foo() {} 
Foo.prototype.a = 'a'; 

function Bar() {} 
Bar.prototype.b = 'b'; 

function Bam() {} 
Bam.prototype.c = 'c'; 

mix(Foo, Bar, Bam); 
console.dir(Foo.prototype); // { a: 'a' } 
console.dir(Foo.prototype.__proto__); // { b: 'b' } 
console.dir(Foo.prototype.__proto__.__proto__); // { c: 'c' } 
+1

Обратите внимание, что 'Object.create (ancestorFn.prototype) .__ proto__ === ancestorFn.prototype'! – Bergi

+1

Просто любопытно: какие проблемы вызывает текущее решение? (обратите внимание, что запрос * другого * решения сейчас ошибочен в соответствии со мной или мета) –

+0

@Begi - Да, понятно, это специально. – Ben

ответ

2

Чтобы настроить цепочку прототипов, напишите .prototype свойство функций конструктора вместо мутирует [[прототип]] существующих объектов прототипа. Конечно, вам нужно будет скопировать все собственные свойства из старого в новый прототип, т. К. Обычно они устанавливаются только после завершения процесса наследования.

Правильно ли это описать это как реализацию mixins?

No. Миксины не мутируют объект, который унаследован. Ваша функция не делает множественное наследование (где Foo наследует от Bar и от Bam), но с одной цепью наследования (где Foo наследует от Bar и Bar наследует от Bam).

И, конечно, ваша функция использует прототипическое наследование, тогда как термин «mixin» относится к методам копирования на объекты (по крайней мере, в JS).

Это можно сделать?

Я бы этим (скорее стандарт) реализации:

function inherit(child, parent) { 
    if (arguments.length > 2) 
     parent = inherit.apply(this, Array.prototype.slice.call(arguments, 1)); 

    child.prototype = Object.create(
     parent.prototype, 
     // get all property descriptor objects from the old child.prototype 
     // will include `constructor` and all manually set properties 
     Object.getOwnPropertyNames(child.prototype).reduce(function(m, n) { 
      m[n] = Object.getOwnPropertyDescriptor(child.prototype, n); 
      return m; 
     }, {}) 
    ); 
    return child; 
} 

является либо предпочтительнее от persepctive производительности?

Я не уверен, насколько плохая мутация прототипа [[prototype]] действительно есть - если это сделано до того, как будут созданы какие-либо экземпляры. Вы должны испытать себя, я уверен, что вы не получите огромных различий в производительности. Конечно, основным недостатком __proto__ является то, что он не поддерживается во всех браузерах.

+0

Под «довольно стандартным», что вы имеете в виду? – Ben

+0

@BenAston: вы можете видеть такие функции 'inherit' довольно часто.По общему признанию дескрипторы дескриптора использования и рекурсия являются скорее фантазией, чем стандартная, она также может выглядеть как [this] (http://stackoverflow.com/a/20230760/1048572). – Bergi

+0

PS: Ой, эта ссылка ссылается на один из моих собственных ответов. См. Другие реализации [здесь] (https://www.google.de/search?q=%22function+inherits%28child%2C+parent%29%22), [там] (https://github.com/csabapalfi /javascript-patterns/blob/master/legacy-patterns.md#classical-temporary-constructor-pattern) или в [узле] (https://nodejs.org/api/util.html#util_util_inherits_constructor_superconstructor). – Bergi

Смежные вопросы