Как вставить что-то в цепочку прототипов?

У меня есть «класс», который по сути является усиленным Array:

function NamedArray(name) {
  var result = [];
  result.name = name;
  return result;
};

var cheeses = new NamedArray('Cheeses');

Это прекрасно работает. Что не работает, так это добавление прототипа для этого "класса":

NamedArray.prototype = {
  nameInAllCaps: function() {
    return this.name.toUpperCase();
  }
};

cheeses.nameInAllCaps();
=> TypeError: Object #<Object> has no method 'nameInAllCaps'

Моей первой мыслью было просто смешать «прототип» с result Array:

function NamedArray(name) {
  var result = [];
  result.name = name;
  for (var prop in NamedArray.prototype) {
    if (NamedArray.prototype.hasOwnProperty(prop) {
      result[prop] = NamedArray.prototype[prop];
    }
  }
  return result;
};

Это работает, но каждый экземпляр имеет собственную копию свойств прототипа. Есть ли способ вставить NamedArray.prototype в цепочку прототипов result Array?


person James A. Rosen    schedule 08.04.2011    source источник
comment
Этот вопрос является дубликатом этого, я думаю: /вопросы/5185122/   -  person idbentley    schedule 08.04.2011
comment
Это, конечно, очень близко. В этом случае, однако, я не хочу объединять вещи в фактические Array.prototype, потому что я не хочу, чтобы они отображались для каждого Array, только NamedArray.   -  person James A. Rosen    schedule 08.04.2011
comment
Я не понял, как вставить экземпляр в цепочку прототипов, но нашел другой способ обойти проблему: вернуть фактический экземпляр NamedArray и установить NamedArray.prototype = new Array();. Это дает NamedArrays полную Array поддержку!   -  person James A. Rosen    schedule 08.04.2011
comment
Однако имейте в виду, что часто используемые версии IE (такие как 8 и, возможно, 9 [я мало проверял эту версию]) могут вести себя очень и очень странно, когда вы пытаетесь наследоваться от Array таким образом. Я бы не рекомендовал делать это, если вам требуется стабильность производственного уровня для вашего проекта. Теоретически, конечно, это работает... но есть еще Microsoft.   -  person mr.stobbe    schedule 15.10.2011
comment
Проверьте stackoverflow. com/questions/2117614/ и второй (но по какой-то причине не отвеченный) ответ (Эрика) немного объясняет, что там происходит при работе с массивами.   -  person mr.stobbe    schedule 15.10.2011


Ответы (1)


Джеймс,

Проблема в том, что ваш "конструктор" возвращает что-то другое, чем вновь выделенный объект, созданный new. (Вместо этого вы создаете массив внутри вашего конструктора и возвращаете его.)

Чтобы исправить этот запутанный аспект вашего кода конструктора, рассмотрите что-то вроде:

function NamedArray(name) {
  this.name = name;
};

NamedArray.prototype = new Array();
NamedArray.prototype.nameInAllCaps =  function() {
  return this.name.toUpperCase();
}

c = new NamedArray("cheeses");
console.log(c.name);
console.log(c.nameInAllCaps());
person Bosh    schedule 11.04.2011
comment
Работает, но не везде. IE имеет проблемы с prototype = new Array() в некоторых браузерах (кажется, что он работает без ошибок, но тогда аксессоры работают некорректно). - person mr.stobbe; 15.10.2011