В чем разница между var и let в Swift и JavaScript?

Ответ

В Swift и JavaScript эти ключевые слова имеют разную семантику, несмотря на одинаковое написание.

Swift

В Swift var и let определяют мутабельность (изменяемость) переменной.

let (константа) var (переменная)
Назначение Неизменяемая ссылка Изменяемая ссылка
Присваивание Только один раз при инициализации Можно многократно
Тип значений Может хранить mutable объекты Может хранить mutable объекты
Оптимизация Компилятор может оптимизировать Меньше оптимизаций

Пример в Swift:

// let - константа (нельзя изменить ссылку)
let constantArray = [1, 2, 3]
// constantArray = [4, 5, 6] // Ошибка: нельзя присвоить новое значение
constantArray.append(4) // OK: содержимое массива можно менять

// var - переменная (можно изменить ссылку)
var variableArray = [1, 2, 3]
variableArray = [4, 5, 6] // OK
variableArray.append(7) // OK

// let с value type
let constantInt = 10
// constantInt = 20 // Ошибка: value type полностью immutable

// Best practice: используйте let по умолчанию, var только когда нужно менять значение

JavaScript

В JavaScript var и let (а также const) определяют область видимости и поведение поднятия (hoisting).

var let const
Область видимости Function-scoped Block-scoped ({}) Block-scoped ({})
Поднятие (hoisting) Инициализируется как undefined Не инициализируется (TDZ) Не инициализируется (TDZ)
Переопределение Можно в той же области Нельзя в той же области Нельзя в той же области
Изменение значения Можно Можно Нельзя (для примитивов)

Пример в JavaScript:

// var - function-scoped
function varExample() {
    if (true) {
        var x = 10;
    }
    console.log(x); // 10 (видна вне блока if)
}

// let - block-scoped
function letExample() {
    if (true) {
        let y = 20;
        console.log(y); // 20
    }
    // console.log(y); // ReferenceError: y is not defined
}

// Temporal Dead Zone (TDZ) для let/const
console.log(a); // undefined (var поднята)
var a = 1;

// console.log(b); // ReferenceError (let в TDZ)
let b = 2;

// const для констант
const PI = 3.14159;
// PI = 3.14; // TypeError: Assignment to constant variable

const obj = { name: "John" };
obj.name = "Jane"; // OK: можно менять свойства объекта
// obj = { name: "Bob" }; // TypeError: нельзя переприсвоить ссылку

Сравнительная таблица

Язык Ключевое слово Основное назначение Область видимости Мутабельность
Swift let Константа (immutable reference) Любая Зависит от типа данных
Swift var Переменная (mutable reference) Любая Зависит от типа данных
JavaScript var Переменная (устаревшее) Function-scoped Можно изменять
JavaScript let Переменная (современное) Block-scoped Можно изменять
JavaScript const Константа (современное) Block-scoped Нельзя переприсвоить

Рекомендации:

  • Swift: Используйте let по умолчанию, var только когда значение должно меняться.
  • JavaScript: Используйте const по умолчанию, let когда значение меняется, избегайте var в новом коде.

Ответ 18+ 🔞

А, ну это же классика, блядь! Сидишь такой, пишешь на Swift, потом переползаешь на JavaScript, и у тебя мозг ебётся, потому что вроде бы те же самые слова, а смысл — хуй пойми какой!

Вот смотри, в Swift всё, в принципе, логично, как у нормальных людей. let — это константа, ссылку поменять нельзя. var — переменная, ссылку можно менять. Всё, пиздец, просто.

let мояКонстанта = [1, 2, 3]
// мояКонстанта = [4, 5, 6] // Ошибка, блядь! Нахуй тебе менять ссылку?
мояКонстанта.append(4) // А вот это можно, потому что сам массив-то мутабельный, ёпта!

var мояПеременная = "Привет"
мояПеременная = "Пока" // Да ради бога, меняй на здоровье, ссылку-то.

Лучшая практика — объявляй всё через let, а var тяни только когда реально надо менять значение. Компилятор тебе спасибо скажет, оптимизирует всё.

А теперь переходим в JavaScript, и тут начинается ёперный театр. Тут var, let и const — это не про мутабельность в первую очередь, а про то, где эта хуйня видна и как её поднимают!

var — это старый дед, который живёт по своим правилам. Область видимости у него — вся функция, и он выёбывается с поднятием (hoisting).

function проверяемVar() {
    console.log(старик) // undefined, но ошибки нет! Его подняли, блядь!
    if (true) {
        var старик = 'Я тут везде';
    }
    console.log(старик) // 'Я тут везде' — виден и здесь, сука!
}

let и const — это уже более адекватные парни. Блочная область видимости. Сказал { — всё, твои переменные отсюда не выйдут.

function проверяемLet() {
    // console.log(молодой) // ReferenceError! Временная мёртвая зона (TDZ), нихуя не видно!
    if (true) {
        let молодой = 'Я только в блоке';
        console.log(молодой) // OK
    }
    // console.log(молодой) // ReferenceError! Где был, там и сдох.
}

А const — это вообще отдельная песня. Нельзя переприсвоить ссылку. Но если это объект — его внутренности менять можно, ебать его в сраку!

const начальник = { имя: 'Иван Петрович' };
начальник.имя = 'Василий Иванович'; // Можно, блядь! Свойства-то меняются!
// начальник = { имя: 'Новый' }; // А вот это НЕЛЬЗЯ! TypeError! Ссылку менять низя!

Короче, сводка для совсем тупых (шутка):

  • Swift: let — ссылка постоянная, var — ссылка переменная. Всё.
  • JavaScript: var — устаревшее говно с функциональной областью видимости. let — нормальная переменная в блоке. const — константная ссылка (но объект внутри ковырять можно).

Что делать-то? В Swift — везде let, пока не припрет. В JavaScript — везде const, пока не припрет. Если припрет — let. А про var забудь, как страшный сон, если, конечно, не поддерживаешь код, которому больше лет, чем тебе.