Операторы ++
и --
изменяются, и они точно не меняют друг друга. Цитирование стандарта 2017 :
12.4.4.1 Семантика раннего времени: оценка
UpdateExpression : LeftHandSideExpression ++
- Пусть
lhs
будет результатом оценки LeftHandSideExpression
.
- Пусть
oldValue
будет ? ToNumber(? GetValue(lhs))
.
- Пусть
newValue
будет результатом добавления значения 1
к oldValue
, используя те же правила, что и для оператора + (см. 12.8.5).
- Выполнить
? PutValue(lhs, newValue)
.
- Возврат
oldValue
.
Это второй шаг, который важен, поскольку он преобразует значение в примитив number
, но между ним и объектом Number
есть небольшая разница, возвращаемая конструктором Number
.
var arr = [new Number(1234)];
function mutateAndRepair(arr) {
console.log(`the value before is ${arr[0]}`);
arr[0]++;
arr[0]--;
console.log(`the value after is ${arr[0]}`);
}
arr[0].foo = 'bar';
console.log(`foo before is ${arr[0].foo}`);
mutateAndRepair(arr)
console.log(`foo after is ${arr[0].foo}`);
Теперь я немного нахальный, потому что я свободно интерпретирую ваше требование, что первый элемент arr
- это "число". И, конечно, вы можете добавить еще одно условие, что значения arr
должны быть «числовыми примитивами», чтобы исключить эту точную форму мутации.
Как насчет другого, более тонкого вопроса. -0
и 0
обрабатываются как одно и то же значение практически всеми способами, кроме Object.is
:
var arr = [-0];
function mutateAndRepair(arr) {
console.log(`the value before is ${arr[0]}`);
arr[0]++;
arr[0]--;
console.log(`the value after is ${arr[0]}`);
}
console.log(`is zero before ${Object.is(0, arr[0])}`);
mutateAndRepair(arr)
console.log(`is zero after ${Object.is(0, arr[0])}`);
Хорошо, вы можете добавить требование, чтобы первый элемент arr
не был -0
. Но все это не попадает в точку . Вы можете утверждать, что практически любой метод не является мутирующим, если вы просто объявите, что будете игнорировать любой случай, в котором будет наблюдаться мутация.
Учитывая ограничения, соответствует ли это общей функциональной парадигме, используемой кодировщиками JavaScript?
Я бы не считал бы, что этот код следует принципам функционального кодирования, и, возможно, даже отклонил бы его в обзоре кода, если бы это было целью проекта. Дело даже не в мельчайших подробностях того, как и обеспечивается ли неизменность всеми путями кода, а в том, что он зависит от внутренней мутации , что делает этот код нефункциональным, на мой взгляд. Я видел множество ошибок в псевдо-функциональном коде, где между шагами mutate
и repair
возникает исключение, которое, конечно, приводит к явным и неожиданным побочным эффектам, и даже если у вас есть catch
/ finally
блок, чтобы попытаться восстановить состояние, также может возникнуть исключение. Возможно, это только мое мнение, но я думаю об неизменности как о части большого функционального стиля , а не просто как о технической особенности данной функции.