Как избежать использования "this" в прототипах Javascript

Здесь мой объект javascript, я хотел бы знать, как избежать использования "this" столько раз в прототипе. Я знаю, что существует много теории и ссылок на прототипную наследование, и на это, вероятно, уже ответили, но поскольку я не смог свести концы с концами, я подумал, что это может стоить другого вопроса.

function shape(smth) {
    this.a = smth
    this.b = 2
    this.c = 3
}

shape.prototype.doCalculus = function () {
    return this.a * this.b + this.c - (2 * (this.b + this.c) + this.a);
}

module.exports = shape

Ответ 1

Если вы хотите публичные члены объекта, они ДОЛЖНЫ ссылаться на указатель this. То, как OO работает в Javascript. Нет альтернативы.

Если у вас много ссылок на одну и ту же переменную внутри функции, вы можете временно поместить ее в локальную переменную, чтобы сохранить некоторую ссылочную логику (так же, как и с любой ссылкой на несколько шагов), но вам все равно придется сначала извлекать используя this.varName.


Существует схема, которая использует "private" переменные-члены в закрытии конструктора и не использует прототип, который может использоваться в некоторых ситуациях, и это позволяет напрямую ссылаться на переменные без использования this:

function shape(smth) {
    var a = smth,
        b = 2,
        c = 3;

    this.doCalculus = function() {
        return a * b + c - (2 * (b + c) + a);
    }
}

module.exports = shape

Для типов объектов, где вы создаете множество экземпляров, это может потреблять немного больше памяти, потому что методы не хранятся в общем прототипе, но создаются отдельно для каждого экземпляра. Есть те, кто утверждает, что разница в потреблении памяти в большинстве случаев не имеет значения.

Ответ 2

В конструкторе можно избежать использования this, используя Object.create, чтобы создать цепочку прототипов, затем объявив ваши свойства непосредственно на результирующем объекте.

function Shape(smth) {
  var shape = Object.create(Shape.prototype);

  shape.a = smth;
  shape.b = 2;
  shape.c = 3;

  return shape;
}

Это устраняет необходимость this в вашей функции Shape, что означает, что нам больше не нужно вызывать ее с помощью new.

new Shape(1); // { a: 1, b: 2, c: 3, __proto__: Shape.prototype }
Shape(1);     // { a: 1, b: 2, c: 3, __proto__: Shape.prototype }

Однако вам все равно придется использовать this внутри ваших методов прототипа для ссылки на правильный экземпляр.

Ответ 3

Вы можете избежать this следующим образом:

function Shape(smth) {
    return {"a": smth, "b": 2, "c": 3 };
}

Но оговорка, которую мне нужно добавить, - это возвращаемый объект, похоже, не играет хорошо с добавлением методов, используя Shape.prototype.methodname

Итак, насколько я могу это сделать, для оригинального примера вам нужно будет сделать:

function Shape(smth) {
    return {"a": smth, 
            "b": 2, 
            "c": 3,
            doCalculus: function () {
                return this.a * this.b + this.c - (2 * (this.b + this.c) + this.a);
            }
    }

Итак, вы все равно закончили с этим (-ами), и вы потеряли преимущества разделения методов в prototype. Я также пытался заставить jslint передать мой код, не отметив поле "Tolerate... this", но я пришел к выводу, что гораздо лучше использовать this. Все, кроме Дугласа Крокфорда, похоже, считают его неотъемлемой частью javascript.

Ответ 4

Если вы хотите избежать "this", вы можете сделать это следующим образом:

const shape = smth => {
      let a = smth,
          b = 2,
          c = 3;
      return {
        doCalculus: () => a * b + c - (2 * (b + c) + a)
      }
    }

    console.log(shape(2).doCalculus()); // -5