Функция Javascript, использующая «this =», дает «Недопустимая левая часть в назначении» - PullRequest
7 голосов
/ 12 марта 2010

Я пытаюсь получить объект JavaScript, чтобы использовать «this» присваивания конструктора других объектов, а также принять все функции-прототипы этих объектов. Вот пример того, что я пытаюсь сделать:

 /* The base - contains assignments to 'this', and prototype functions
  */
 function ObjX(a,b) {
     this.$a = a;
     this.$b = b;
 }

 ObjX.prototype.getB() {
     return this.$b;
 }

 function ObjY(a,b,c) {
    // here's what I'm thinking should work:
    this = ObjX(a, b * 12); 
    /* and by 'work' I mean ObjY should have the following properties:
     * ObjY.$a == a, ObjY.$b == b * 12,
     * and ObjY.getB == ObjX.prototype.getB
     * ... unfortunately I get the error: 
     *     Uncaught ReferenceError: Invalid left-hand side in assignment
     */

    this.$c = c; // just to further distinguish ObjY from ObjX.
 }

Я был бы признателен за ваши мысли о том, как ObjY включает в себя назначения ObjX для 'this' (т. Е. Не нужно повторять все this.$* = * назначения в конструкторе ObjY) и чтобы ObjY принимал ObjX.prototype.

Моя первая мысль - попробовать следующее:

function ObjY(a,b,c) {
   this.prototype = new ObjX(a,b*12);
}

В идеале я хотел бы научиться делать это прототипным способом (то есть не нужно использовать какие-либо из этих «классических» заменителей ООП, таких как Base2 ).

Может быть примечательно, что ObjY будет анонимным (например, factory['ObjX'] = function(a,b,c) { this = ObjX(a,b*12); ... }) - если я правильно понял терминологию.

Спасибо.

1 Ответ

19 голосов
/ 12 марта 2010

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

В качестве обходного пути можно использовать методы call или apply для запуска функции конструктора ObjX в объекте this объекта ObjY:

function ObjY(a,b,c) {
  ObjX.call(this, a, b * 12); 
  this.$c = c;
}

В приведенном выше примере функция ObjX выполняется с изменением своего значения this, поэтому все расширения свойств, которые вы делаете для этого объекта в этой функции, будут отражены в новом объекте, на который ссылается значение this конструктор ObjY.

Как только метод call завершится, объект this будет расширен, и вы сможете сделать больше расширений свойств, например, добавив значение $c.

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

Я думаю, вы могли бы спутать свойство конструкторов prototype с внутренним свойством [[Prototype]], которое есть у всех объектов.

Свойство [[Prototype]] может быть установлено только оператором new (через внутреннюю операцию [[Construct]]), это свойство не может быть изменено (хотя некоторые реализации, такие как Mozilla) во-первых, вы можете получить к нему доступ через obj.__proto__;, а в ECMAScript 5 был введен метод Object.getPrototypeOf, но я бы не рекомендовал вам напрямую связываться с ним).

На самом деле, когда ваша функция конструктора выполняется, внутреннее свойство [[Prototype]] объекта, на которое ссылается значение this, уже было установлено на свойство prototype его конструктора.

Таким образом, как отмечает @Anurag, вы можете установить ObjY.prototype для вновь созданного ObjX объекта:

function ObjY(a,b,c) {
  ObjX.call(this, a, b * 12); 
  this.$c = c;
}

ObjY.prototype = new ObjX();
ObjY.prototype.constructor = ObjY;

Это будет означать, что ваш ObjY наследует также свойства, добавленные к ObjX.prototype, и, как вы видите, я изменил ObjY.prototype.constructor, поскольку назначение в строке выше заставит это свойство ошибочно указывать на ObjX.

Рекомендуемые статьи:

...