در نگاه اول کار let با var یکیه و هر دو متغیر تعریف میکنند که یا global هستند یا فقط محدود به functionیی که در آن ساخته شده اند هستند.

let message = 'Hello!'; // define the variable and assign the value

alert(message); // Hello!
function sayHi() {
var phrase = "Hello"; // local variable, "var" instead of "let"

alert(phrase); // Hello
}

sayHi();

alert(phrase); // Error, phrase is not defined

ولی فرقشون اینکه var هیچ block scope سرش نمیشه. یعنی یا global تعریف شده یا function-wide ، ولی در هر بلاکی باشند بیرون از آن قابل دسترسی اند.

if (true) {
var test = true; // use "var" instead of "let"
}

alert(test); // true, the variable lives after if

در مثال بالا اگه از let استفاده کرده بودیم دیگه alert کار نمیکرد چون let فقط محدود به blockیی است که در آن ساخته میشود. ولی var اهمیتی به block کد ها نمیده و پس درواقع اینجا یک متغیر global داریم. 

اگه var در blockیی داخل یک function باشه، در واقع یک var با خاصیت function-level داریم.

function sayHi() {
if (true) {
var phrase = "Hello";
}

alert(phrase); // works
}

sayHi();
alert(phrase); // Error: phrase is not defined

در کد بالا میبینید که var متوجه بلاک if نیست چون در javascript قدیم block ها هیچ مرزی نداشتن.

فرق دیگه hoisting است که var در اول function ها تعریف میشود. چه شما بعد چند خط کد یا بلاک انها رو تعریف کیند، درواقع آنها اول از هرچیزی در function خونده میشوند.

این تفاوت ها مشکل سازند چون نمیتونیم block-local variables بسازیم یا hoisting فقط ارور برامون بوجود میاره. به این دلایل در اسکریپت های جدید var کم دیده میشه.