Как я могу увидеть цепочку прототипов объекта Javascript? - PullRequest
19 голосов
/ 11 февраля 2010

С учетом следующего кода:

function a() {}
function b() {}
b.prototype = new a();
var b1 = new b();

Мы можем утверждать, что a был добавлен в цепочку прототипов b. Отлично. И, все следующее верно:

b1 instanceof b
b1 instanceof a
b1 instanceof Object

Мой вопрос: что, если мы не узнаем происхождение b1 раньше времени? Как мы можем обнаружить членов его цепи прототипов? В идеале я бы хотел массив типа [b, a, Object] или ["b", "a", "Object"].

Возможно ли это? Я полагаю, что где-то на SO я видел ответ, в котором описывалось, как это выяснить, но я не могу найти его снова.

Ответы [ 3 ]

7 голосов
/ 11 февраля 2010

Ну, ссылка прототипа между объектами ([[Prototype]]) является внутренней, некоторые реализации, такие как Mozilla, представляют ее как obj.__proto__.

Метод Object.getPrototypeOf в 5-м издании ECMAScript - это то, что вам нужно, но сейчас он не реализован на большинстве движков JavaScript.

Посмотрите на эту реализацию Джона Резига, в ней есть ловушка, она опирается на свойство constructor двигателей, которые не поддерживают __proto__:

if ( typeof Object.getPrototypeOf !== "function" ) {
  if ( typeof "test".__proto__ === "object" ) {
    Object.getPrototypeOf = function(object){
      return object.__proto__;
    };
  } else {
    Object.getPrototypeOf = function(object){
      // May break if the constructor has been tampered with
      return object.constructor.prototype;
    };
  }
}

Помните, что это не на 100% надежно, поскольку свойство constructor является изменяемым для любого объекта.

2 голосов
/ 11 февраля 2010

edit - Этот ответ с 2010 года и довольно устарел. С тех пор в язык добавлен API Object.getPrototypeOf(), что значительно упрощает процесс.


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

function getPrototypes(o) {
  return (function gp(o, protos) {
    var c = o.constructor;
    if (c.prototype) {
      protos.push(c.prototype);
      return gp(c.prototype, protos);
    }
    return protos;
  })(o, []);
}

(может быть) (а может и нет :-) дайте мне секунду) (ну дерьмо; я думаю, что это возможно, но игнорируйте этот код)

[править] Вау, это просто поражает меня - эта функция близка, но не совсем правильна; Создание цепочки прототипов странно, и я чувствую себя напуганным и одиноким. Предлагаю обратить внимание только на потрясающую @CMS выше.

0 голосов
/ 18 мая 2015

Вот отправная точка:

Object.prototype.getConstructorNames=function(){
        return Object.keys(window).filter(function(e){
            return typeof window[e]==="function" && this instanceof window[e]},this)
    }

Конечно, это действительно неполно, но я думаю, что это будет работать в большинстве случаев, и если кто-то захочет добавить к нему, они могут.

...