Является ли «это» изменчивым состоянием в JavaScript? - PullRequest
1 голос
/ 10 января 2020

Можно думать о этом как о неявной переменной, установленной во время выполнения. Если для него можно установить разные значения, это может повлиять на поведение функции и значение, которое она возвращает, что делает функцию нечистой. В приведенном ниже примере функция objOne.addTwo вызывает только другую чистую функцию, но из-за this ее можно изменить.

Пример

const objOne = {
  getTwo: () => 2,
  addTwo: function (num) {
    return num + this.getTwo();
  }
}
const objTwo = {
  getTwo: () => 3
}
console.log(objOne.addTwo(2)); // Returns 4
console.log(objOne.addTwo.call(objTwo, 2)); // Returns 5 instead of 4

Вопрос

Как правило, это следует считать "изменяемым состоянием"?

Ответы [ 3 ]

3 голосов
/ 10 января 2020

Нет, ключевое слово this само по себе не считается изменяемым состоянием. Рассмотрим следующую программу.

const objOne = {
  getTwo: () => 2,
  addTwo: function (self, num) {
    return num + self.getTwo();
  }
}

const objTwo = {
  getTwo: () => 3
}

console.log(objOne.addTwo(objOne, 2)); // Returns 4
console.log(objOne.addTwo(objTwo, 2)); // Returns 5 instead of 4

Данная программа явно не имеет мутаций. Это то же самое, что и ваша оригинальная программа, за исключением того, что она использует формальный параметр вместо использования ключевого слова this.


Однако this обычно используется вместе с мутацией в OOP. Например, рассмотрим следующий класс.

class Vec2 {
    constructor(x, y) {
        this.x = x;
        this.y = y;
    }

    add(that) {
        this.x += that.x;
        this.y += that.y;
    }
}

const v1 = new Vec2(1, 2);
const v2 = new Vec2(3, 4);

v1.add(v2);

console.log(v1); // { x: 4, y: 6 }

Очевидно, что вы можете иметь мутацию, даже не используя this.

const Vec2 = (x, y) => ({ x, y });

const add = (self, that) => {
    self.x += that.x;
    self.y += that.y;
};

const v1 = Vec2(1, 2);
const v2 = Vec2(3, 4);

add(v1, v2);

console.log(v1); // { x: 4, y: 6 }

Итак, this - это просто особый параметр сортировки. Само по себе это не изменчиво. Однако вы можете изменить его так же, как и любой другой параметр.


Большая проблема с ключевым словом this и ключевым словом new заключается в том, что они являются особыми случаями. Обычно вы вызываете функцию как foo(x, y, z), но с this вам придется вызывать функцию как foo.call(x, y, z), а с new вы должны вызывать функцию как new foo(x, y, z).

Эти особые случаи затрудняют повторное использование функций более высокого порядка. Например, обычно вы можете сделать [1, 2, 3].map(foo), но что, если для звонка на foo необходимо добавить префикс new? Тогда вам нужно будет написать [1, 2, 3].map((...args) => new foo(...args)). Точно так же, что если foo необходимо вызвать с помощью .call? Затем вам нужно будет написать [1, 2, 3].map((...args) => foo.call(...args)).

Очевидно, что эти особые случаи усложняют жизнь, по крайней мере, в случае функционального программирования. Процитируем Дзэн Python.

Особые случаи не настолько особенные, чтобы нарушать правила.

TLDR: Избегайте использования this и new при написании программ в функциональном стиле.

2 голосов
/ 10 января 2020

Это скорее философский вопрос ИМО. Я думаю, это зависит от того, что вы понимаете под изменяемым состоянием . Из документов мы читаем:

Он не может быть установлен присваиванием во время выполнения и может отличаться при каждом вызове функции.

Это ясно объясняет, что this нельзя установить во время выполнения функции, но она может отличаться в зависимости от того, как вы вызываете функцию. Так что, если мы говорим о переназначении this, то нет, это не изменяемое состояние, потому что невозможно изменить его значение после его установки. Но мы можем изменить его, вызвав функцию по-другому.

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

0 голосов
/ 10 января 2020

С моей точки зрения, я не говорю , что является изменяемым состоянием.

И то, что произошло, связано с Javascript Лексическим охватом и ScopeManager

Когда ScopeManager находит этот в вашей функции, ScopeManager начинает поиск в своем Lexical Scope о ближайшее это значение, если вы не используете Hard Binding , как вы использовали при использовании call

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...