var 关键字
在JavaScript
中,常用var
声明一个变量。
语法
| var varname1 [= value1] [, varname2 [=value2]] ...[,varnameN[= valueN]]; |
复制
varnameN
: 变量名。遵循命名规范valueN
: 变量的初始化值,可以是任何合法的表达式,默认值:undefined
描述
-
变量声明,无法发生在何处,都在执行任何代码之前进行处理。
-
var
声明变量的作用域是其当前的执行上下文。
-
在任何函数外声明的变量为全局变量
-
在函数内声明的变量为局部变量
-
当赋值给未声明的变量时,执行赋值后,该变量会被隐式地创建为全局变量。(它将成为全局对象的属性)
-
声明与未声明变量之间的差异:
- 声明变量的作用域限制在声明位置的上下文中。而非声明变量总是全局的。
| function x() { |
| y = 1; |
| var z = 2; |
| } |
| |
| x(); |
| |
| console.log(y); |
| console.log(z); |
复制
- 声明变量在任何代码执行前创建,而非声明变量只有在执行赋值操作的时候才会被创建。
| console.log(a); |
| console.log('still going...'); |
| var a; |
| console.log(a); |
| console.log('still going...'); |
复制
3.声明变量是其所在上下文的不可配置属性,非声明变量是可配置的(如非声明变量可以被删除)
| var a = 1; |
| b = 2; |
| |
| delete this.a; |
| delete this.b; |
| |
| console.log(a, b); |
| |
复制
变量提升
变量声明总是在任何代码执行之前处理的,所以在代码中的任意位置声明变量总是等于在代码开发声明。意味着变量可以在声明之前使用。这就是变量提升(hoisting)。
| function do_something() { |
| console.log(bar); |
| var bar = 111; |
| console.log(bar); |
| } |
| do_something(); |
复制
多个变量声明,初始化
复制
隐式全局变量和外部函数作用域
| var x = 0; |
| |
| console.log(typeof z); |
| |
| function a() { |
| |
| var y = 2; |
| |
| console.log(x, y); |
| |
| function b() { |
| |
| x = 3; |
| y = 4; |
| z = 5; |
| } |
| b(); |
| |
| console.log(x, y, z); |
| } |
| |
| a(); |
| console.log(x, z); |
| console.log(typeof y); |
复制
let
- 用法与 var 用法一致,语义上有所不同
- 用
let
声明一个变量,使用的是词法作用域
或块级作用域
。 - 块级作用域变量:在包含他们的块或
for
循环以外是不能访问的。
| function f(input: boolean) { |
| let a = 100; |
| |
| if (input) { |
| |
| let b = a + 1; |
| |
| return b; |
| } |
| |
| return b; |
| } |
复制
- 在 catch 语句里声明的变量也具有同样的作用域规则。
| try { |
| throw 'oh no!'; |
| } catch (e) { |
| console.log('Oh well.'); |
| } |
| |
| |
| console.log(e); |
复制
- 块级作用域的变量不能在声明之前读或写,虽然这些变量始终存在于“他们的作用域里”,但是直到声明他们的代码之前的区域都属于
暂时性死区
。
复制
- 可以一个拥有块级作用域变量被声明前获取它, 只是不能在变量声明前去调用这个函数。
| function foo() { |
| return a; |
| } |
| |
| |
| |
| foo(); |
| |
| let a; |
复制
重定义以及屏蔽
| |
| function f(x) { |
| var x; |
| var x; |
| |
| if (true) { |
| var x; |
| } |
| } |
复制
let
声明时,同在一个作用域内不能声明相同的变量。
| function f(x) { |
| |
| |
| let x = 100; |
| } |
| |
| function g() { |
| let x = 100; |
| var x = 100; |
| |
| } |
复制
| function f(condition, x) { |
| if (condition) { |
| let x = 100; |
| return x; |
| } |
| return x; |
| } |
| |
| f(false, 0); |
| f(false, 0); |
复制
- 一个嵌套作用域引入一个行为称作屏蔽。(尽量避免使用屏蔽,可以用不同变量名)
| |
| function sumMatrix(matrix: number[][]) { |
| let sum = 0; |
| for (let i = 0; i < matrix.length; i++) { |
| var currentRow = matrix[i]; |
| for (let i = 0; i < currentRow.length; i++) { |
| sum += currentRow[i]; |
| } |
| } |
| return sum; |
| } |
复制
- 当
let
声明在循环体时,不仅引入一个新的变量环境,而且针对每次迭代都会创建一个新作用域。
| for (let i = 0; i < 10; i++) { |
| setTimeout(function () { |
| console.log(i); |
| }, 100 * i); |
| } |
| |
| |
| |
复制
const
- 与
let
拥有相同的作用域规则,但是不能重新赋值。 - 声明是必须初始化。
| const numLivesForCat = 9; |
| const kitty = { |
| name: 'Aurora', |
| numLives: numLivesForCat, |
| }; |
| |
| |
| kitty = { |
| name: 'Danielle', |
| }; |
复制