Я хочу передать переменную в функцию и чтобы функция изменила её значение.
Я знаю, что могу сделать это с помощью объекта, но интересно, есть ли другой способ, о котором я не подумал.
Вот что я хочу сделать, но, конечно, это не работает так, как я хочу:
function test1(vari) {
vari = 2;
}
var myvar1 = 1;
test1(myvar1);
console.log(myvar1);
Это работает, но я не действительно хочу, чтобы все переменные были объектами:
function test2(vari) {
vari.val = 2;
}
var myvar2 = { val: 1 };
test2(myvar2);
console.log(myvar2.val);
Это тоже работает, но это неприемлемое решение:
function test3(vari) {
eval(vari + ' = 2;');
}
var myvar3 = 1;
test3('myvar3');
console.log(myvar3);
Существует ли более хороший вариант, чем эти?
Это может быть не то, что вы ищете, но возможно, попробуйте что-то вроде:
function test1(vari) {
return vari += 2;
}
var myvar1 = test1(myvar1);
console.log(myvar1);
Ответ
Вопрос, с которым вы столкнулись, касается передачи переменных по ссылке, чтобы функция могла изменять их значение. В некоторых языках программирования есть возможность напрямую изменять значения переменных, переданных в функции, но в JavaScript это не так просто, поскольку примитивные типы (например, числа и строки) передаются по значению, а не по ссылке. Рассмотрим несколько подходов для достижения желаемого результата.
1. Использование объектов
Вы уже упомянули, что можете обернуть переменную в объект, и это действительно один из самых простых способов передать "по ссылке". Например:
function test(vari) {
vari.value = 2;
}
let myvar = { value: 1 };
test(myvar);
console.log(myvar.value); // 2
2. Использование массива
Другой подход — использовать массив. Массивы, как и объекты, передаются по ссылке.
function test(vari) {
vari[0] = 2;
}
let myvar = [1]; // массив с одним элементом
test(myvar);
console.log(myvar[0]); // 2
3. Возврат значения
Если вам не хочется использовать объекты или массивы, вы можете вернуть новое значение из функции, как вы уже упомянули в своем вопросе:
function test(vari) {
return vari + 1; // например, увеличиваем на 1
}
let myvar = 1;
myvar = test(myvar);
console.log(myvar); // 2
4. Использование функции более высокого порядка
Вы можете создать обертку, которая позволит вам изменять переменные.
function modifyVar(obj) {
return function(newValue) {
obj.value = newValue;
};
}
let myvar = { value: 1 };
let setMyVar = modifyVar(myvar);
setMyVar(2);
console.log(myvar.value); // 2
5. Использование Proxy
Если вы хотите более сложное управление, вы также можете использовать Proxy
для перехвата изменений:
let handler = {
set(target, property, value) {
console.log(`${property} изменено на ${value}`);
target[property] = value;
return true;
}
};
let myvar = new Proxy({ value: 1 }, handler);
myvar.value = 2; // "value изменено на 2"
console.log(myvar.value); // 2
Заключение
Каждый из приведенных выше методов имеет свои преимущества и недостатки. Выбор метода зависит от ваших конкретных потребностей и контекста вашего кода. В большинстве случаев, если вам нужно изменять значения, имеет смысл использовать объекты или массивы. Если ваши данные имеют простой тип, возврат значения из функции — это элегантное решение, которое также легко читается и поддерживается.