Добавление прототипа в литерал объекта - PullRequest
7 голосов
/ 10 августа 2010

У меня есть какой-то объект, скажем son, который я хотел бы унаследовать от другого объекта father.

Конечно, я могу сделать функцию конструктора для отца, например

Father = function() {
  this.firstProperty = someValue;
  this.secondProperty = someOtherValue;
}

А затем используйте

var son = new Father();
son.thirdProperty = yetAnotherValue;

, но это не совсем то, что я хочу.Поскольку son будет иметь много свойств, было бы более читабельно, если бы сын был объявлен как литерал объекта.Но тогда я не знаю, как установить его прототип.

Выполнение чего-то вроде

var father = {
  firstProperty: someValue;
  secondProperty: someOtherValue;
};
var son = {
  thirdProperty: yetAnotherValue
};
son.constructor.prototype = father;

не сработает, поскольку цепочка прототипов кажется скрытой и не заботится о сменеconstructor.prototype.

Я думаю, что могу использовать свойство __proto__ в Firefox, например,

var father = {
  firstProperty: someValue;
  secondProperty: someOtherValue;
};
var son = {
  thirdProperty: yetAnotherValue
  __proto__: father
};
son.constructor.prototype = father;

, но, насколько я понимаю, это не стандартная функция языкаи лучше не использовать его напрямую.

Есть ли способ указать прототип для литерала объекта?

Ответы [ 3 ]

11 голосов
/ 10 августа 2010

Вы правы, __proto__ - это нестандартное свойство, и есть только два стандартных способа установки [[Prototype]] нового объекта:

  • С помощью конструктора и оператора new (как вы уже упоминали).
  • Использование метода ECMAScript 5 Object.create.

Object.create пока не широко поддерживается (работает на IE9Pre3 +, Firefox 3.7 Alpha +, Chrome 5+ Safari 5+, Rhino 1.7), но в какой-то момент все реализации будут соответствовать спецификации ES5.

Может принимать два аргумента: первый - это объект, который будет использоваться как [[Prototype]] нового объекта, а второй - еще один объект, в котором могут быть описаны собственные свойства (в той же структуре, что и вы бы использовали Object.defineProperties).

Например:

var father = {
  firstProperty: 1,
  secondProperty: 2
};

var son = Object.create(father, {
  thirdProperty: {
    value: 'foo'
  }
});

father.isPrototypeOf(son); // true
son.firstProperty; // 1

Внутреннее son свойство [[Prototype]] будет ссылаться на father и содержать свойство значения с именем thirdProperty.

3 голосов
/ 29 ноября 2011

Это неправильно, jmar777.Например, если у вас

var X = function() {};
X.prototype = {
  protoFunc1: function() { console.log('p1');},
  protoFunc2: function() { console.log('p2');}
};

X.protoFunc1(); // is not a function 

Это означает, что то, что вы делаете:

X.prototype = {}

- это просто создание объекта с именем prototype.Не фактический прототип.Чтобы использовать прототип, вы должны использовать функции конструктора.

, если, однако, измените его на этот (метод конструктора)

function X(){};
X.prototype.protoFunc1 = function() { 
    console.log('p1');
}
X.prototype.protoFunc2 = function() { 
    console.log('p2');
}

var x = new X();
x.protoFunc1(); //'p1'

Это будет работать.

Либо идите объектлитеральный метод без использования прототипа или использование метода contructor с использованием прототипа.

0 голосов
/ 10 августа 2010

Указание прототипа для литерала объекта немного «утомительно», так как вы в первую очередь захотите создать прототип для объектов, создаваемых с использованием синтаксиса конструктора (например, new X ()).Не сказать, что это невозможно ... но это странно.Аналогичный шаблон, который хорошо себя зарекомендовал (например, использует jQuery), - вместо этого определить прототип как литерал объекта.Например:

var X = function() {};
X.prototype = {
  protoFunc1: function() {},
  protoFunc2: function() {}
};
...