Как избежать использования "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