DEV Community

NikiMunger
NikiMunger

Posted on

JS中的对象、var let const 在JS里的区别、JS中的作用域

1. JS中的对象

JS 的对象是“动态的”,可以随时增删属性。
object是一个对象,在JS中可以通过object[key] = value,给object对象增加key属性。

const student = {};
student['name'] = '小明';// 或者 student.name = '小明';
console.log(student);
Enter fullscreen mode Exit fullscreen mode

输出

{name: '小明'}
Enter fullscreen mode Exit fullscreen mode

但是

const student = {};
student[name] = '小明';
console.log(student);
Enter fullscreen mode Exit fullscreen mode

输出

{"": '小明'}//或者直接报错
Enter fullscreen mode Exit fullscreen mode

因为student[name] = '小明';此时 name 是一个未定义的变量,而不是字符串。


2. var、let、const 在JS里的区别

1.作用域(scope)

var 是函数作用域(function-scoped)或全局(若在全局声明)。
let/const 是块级作用域(block-scoped),即 { ... } 之内。

function test() {
  if (true) {
    var a = 1;
    let b = 2;
    const c = 3;
  }
  console.log(a); // 1  —— var 在函数内可访问
  console.log(b); // ReferenceError(引用错误): b is not defined
  console.log(c); // ReferenceError: c is not defined
}
test();
Enter fullscreen mode Exit fullscreen mode

2.提升(hoisting)与暂时性死区(TDZ)

JavaScript 执行代码前,引擎会先扫描整个作用域里的变量和函数声明。它会先“记住”有哪些变量或函数存在。这个过程叫 “提升”(Hoisting)。

所谓“提升”,意思是:

  • 声明语句虽然写在后面,但在执行时, 它的“声明部分”会像被提前到作用域的最上方一样生效。
  • 不是真的移动代码,只是引擎提前知道了变量的名字。

所以,在代码执行时,你可以在声明之前访问这个变量——
不过,不同的声明方式行为不同(这是重点!)。

区别

  • var
console.log(a); // 输出: undefined
var a = 10;
Enter fullscreen mode Exit fullscreen mode

解释:
引擎执行前,会先把这段代码“内部理解”为:

var a;       // 声明被提前了(提升)
console.log(a);
a = 10;      // 赋值依然在原来的地方
Enter fullscreen mode Exit fullscreen mode

所以 console.log(a) 不会报错,但此时 a 还没赋值,是 undefined。

  • let / const
console.log(b); // ReferenceError
let b = 20;
Enter fullscreen mode Exit fullscreen mode

为什么这里报错?
let 和 const 也被提升了,但在它们真正执行到声明语句之前,会处于“暂时性死区 (TDZ)”
在这段“死区”中,访问变量会直接报错(引擎禁止你使用未初始化的变量)。

  • const 还要求声明时必须初始化。

3.重新赋值(re-assignment)与重新声明(re-declare)

  • var:可以重新赋值,也可以在同一作用域重复声明(不会报错)。
  • let:可以重新赋值,但不允许在相同作用域重复声明。
  • const:不能重新赋值,且不能重复声明。必须在声明时初始化。

示例:

var a = 1;
var a = 2; // 合法
a = 3;     // 合法

let b = 1;
// let b = 2; // SyntaxError: Identifier 'b' has already been declared
b = 2;       // 合法

const c = 1;
// c = 2; // TypeError: Assignment to constant variable.
// const c = 3; // SyntaxError

Enter fullscreen mode Exit fullscreen mode

4.const 与对象/数组(引用的可变性)

const 是对绑定(binding) 的限制:你不能把标识符重新绑定到另一个值,但如果值本身是对象/数组,其内部是可变的。

const obj = {x: 1};
obj.x = 2;          // 合法 —— 修改对象属性
// obj = {x: 3};   // TypeError: Assignment to constant variable.

const arr = [1,2];
arr.push(3);        // 合法
// arr = [4,5];    // TypeError

Enter fullscreen mode Exit fullscreen mode

5. 全局对象行为(浏览器中的 window)

在全局作用域:

  • var foo = ... 会成为 window.foo(浏览器环境)。
  • let / const 不会创建 window 的属性(不会污染全局对象)。
var g = 1;
let h = 2;
console.log(window.g); // 1
console.log(window.h); // undefined
Enter fullscreen mode Exit fullscreen mode

6.推荐实践

  1. 默认使用 const:多数变量不需要重新绑定,使用 const 能防错并表达意图。
  2. 需要修改时用 let:例如循环计数、累加器、可变状态。
  3. 避免使用 var:只有在你需要兼容非常旧的代码或特殊场景时才考虑。
  4. 注意 TDZ:不要在 let/const 声明前访问变量(会抛错)。
  5. 对象/数组也要留心可变性:若需要完全不可变结构,使用 Object.freeze 或不可变库。

3. JS中的作用域

作用域(Scope) 就是变量(或函数)在代码中的可访问范围。
你在哪能访问到这个变量?在哪访问不到?这就是由「作用域」决定的。

1.JavaScript 主要有 4 种作用域

作用域类型 关键字 举例 特点
1️⃣ 全局作用域(Global Scope) 脚本最外层声明的变量 任何地方都能访问
2️⃣ 函数作用域(Function Scope) var, 函数声明 函数内部定义的变量 只在函数内可访问
3️⃣ 块级作用域(Block Scope) let, const { ... } 内定义的变量 只在花括号内可访问
4️⃣ 模块作用域(Module Scope) ES Module import/export 文件内 只在当前模块文件有效

2.全局作用域

在最外层定义的变量(不在任何函数或块中)属于全局作用域。

var x = 10;

function show() {
  console.log(x); // 可以访问
}

show();
console.log(x);   // 也可以访问
Enter fullscreen mode Exit fullscreen mode

全局作用域的变量在任何地方都能访问。
但要小心:污染全局命名空间。

浏览器里,全局变量会挂到 window 对象上:

var a = 1;
console.log(window.a); // 1
Enter fullscreen mode Exit fullscreen mode

3.函数作用域(Function Scope)

每个函数都会创建自己的独立作用域。

function test() {
  var y = 20;
  console.log(y); // 函数内部可访问
}

test();
console.log(y);   // ReferenceError
Enter fullscreen mode Exit fullscreen mode

var 定义的变量在函数作用域内有效,外部无法访问。

4.块级作用域(Block Scope)

由 { ... } 包裹的区域,比如:

  • if、for、while、switch 块
  • 普通花括号 {}

在块级作用域内用 let 或 const 声明的变量,只在该块中有效。

{
  let a = 1;
  const b = 2;
  var c = 3;
}
console.log(c); // 3
console.log(a); // ReferenceError
console.log(b); // ReferenceError
Enter fullscreen mode Exit fullscreen mode
  • var 不受块级作用域限制(只有函数作用域)。
  • let 和 const 是真正的块级作用域变量。

5.模块作用域(Module Scope)

ES6 引入模块系统(.js 文件中使用 import / export)。
每个模块文件自动拥有独立作用域,模块间互不干扰。

// fileA.js
export const name = "Alice";

// fileB.js
import { name } from "./fileA.js";
console.log(name); // "Alice"
console.log(window.name); // ❌ undefined (不是全局变量)
Enter fullscreen mode Exit fullscreen mode

模块作用域相当于一种“隔离的全局作用域”,不会污染 window。

6.作用域嵌套(Scope Chain)

作用域是可嵌套的:

const a = 1;

function outer() {
  const b = 2;

  function inner() {
    const c = 3;
    console.log(a, b, c); // ✅ 都能访问
  }

  inner();
}

outer();
Enter fullscreen mode Exit fullscreen mode

查找规则:
当代码访问一个变量时,JavaScript 会:

  1. 先在当前作用域找;
  2. 找不到就往上层作用域(外层函数 / 全局)查;
  3. 一直找到全局为止;
  4. 若全都找不到 → 抛出 ReferenceError。

这个查找链条称为 “作用域链(Scope Chain)”。

Top comments (0)