JS声明
在我们的日常编码的过程中必须掌握的语法,那么我们今天一起学习一下
var
JS是一个弱类型的语言定义,针对声明的变量是不需要进行任何的类型声明
// var 声明语句
// a 变量名
// = 赋值表达式
// "hello world" 字符串类型的变量值
var a = "hello world"
var
语句主要在可以在可以用来在全局作用域跟函数作用域进行声明,并且存在变量提升,具体案例如下:
// undefined(变量提升,没有报错)
console.log(a);
var a = 1;
// 1
console.log(a)
function fn () {
console.log(a);
console.log(b);
var b = 2;
console.log(b);
}
// 1
// undefined(变量提升,没有报错)
// 2
fn()
// 错误: Uncaught ReferenceError: b is not defined
console.log(b)
从上述案例我们可以了解到以下3点:
var
的声明虽然提前了,但是赋值操作依然是在原代码行执行- 函数作用域可以访问外层作用域中声明的变量,反过来是不行的!
- 虽然存在声明提升,但是使用没有声明的变量是会抛出
ReferenceError类型
的报错的
变量提升: 个人认为变量提升实际上是类似声明声明提前的操作,相当于是检索当前作用域下使用
var
声明的变量名,先进行声明操作,然后再执行同步代码
全局声明
通常情况下我们很少会用到全局声明,虽然大多数情况下,它会被放入var
的声明中,不过我在这里还是单独区分出来,方便自己进行场景区分
a = 1
// 1
console.log(a)
function fn () {
b = 2
}
fn()
// 2
console.log(b)
全局声明是没有变量提升的概念的,因为全局操作的这种方式,必须赋值才能生效,当然你也可以给一个变量赋值undefined
(虽然有点脱了裤子放屁)
在实际使用场景中实际上并不推荐这种写法:
1. 从代码阅读很难查找变量到底是在什么地方进行声明的,很有可能是在什么几千层嵌套的CallBack中,让你痛不欲生
2. 这种书写方式很容易造成阅读障碍,不清楚你现在到底做的是一个全局声明,还是局部变量赋值的操作。
let
let
是es6中新的声明语句。与var
不同的是,除了存在全局作用域跟函数作用域以外,同时存在块级作用域{ ... }
。let
并不存在变量提升,除此之外let
语句还存在暂时性死区,比如下列场景
// ReferenceError: a is not defined
console.log(a)
let a = 1
// 1
console.log(a)
{
// ReferenceError: Cannot access 'a' before initialization
console.log(a)
let a = 2
// 2
console.log(a)
let b = 3
var c = 4
}
// ReferenceError: b is not defined
console.log(b)
// 4
console.log(c)
var
声明语句不存在块级作用域,所以可以访问到c
的变量,但是因为let
语句存在块级作用域所以我们无法访问到变量b
。 另外看到ReferenceError: Cannot access 'a' before initialization
这个报错就是暂时性死区的错误格式,它跟常见的变量不存在的错误信息实际上是不一样的,所以在一定程度上我们可以理解为,let
语句也是存在声明提前的,只是在源代码行声明执行前,是不可以引用(可能是为了更加的规范)。
const
const
语句实际上跟let
语句一样,也是es6
新增的声明语句(同时具备块级作用域以及暂时性死区),区别在const
语句主要是用来声明常量的,变量值是不可变的(引用类型的情况下,引用对象不可发生变化)。并且在声明常量时,就需要赋值(这点有点像全局声明)
// SyntaxError: Missing initializer in const declaration
const a
const b = 1
// TypeError: Assignment to constant variable.
b = 2
const c = { someKey: 1 }
// success!
c.someKey = 2
由于 暂时性死区 跟 块级作用域 的行为跟let
语句是保持一致的就没有展示
function
函数声明
是一个很容易被忽略的声明语句,它跟var
语句有变量提升的概念,但是不同的点在于大部分情况下,只要你在当前作用域范围内,有进行函数声明,也是可以进行提交的函数调用的(也就是指这一刻函数已经具有值的存在)。函数声明
具有全局作用域跟函数作用域,没有块级作用域,如下所示
function a () {
console.log('all')
}
{
// 'all'
a()
{
function a () {
console.log('block')
}
}
}
function b () {
a()
function a () {
console.log('function')
}
}
// 'block'
a();
// 'function'
b();
var a = 1
// 1
console.log(a)
理论上函数声明
跟var
语句都是存在提升的,理论上var
语句的优先级会更高,由于var
声明后,才轮到函数声明
, 上述的a()
在使用的过程中才没有报TypeError: a is not a function
的错误。
class 以及 import
es6中新增的class
语句其实也算是一种声明,不过它更像是构造函数函数的语法糖。使用方法的话就不详细介绍了。同时 import
我会在后续的 [模块化]复习过程中提到所以也不在这里赘述。(这里留个坑🕳️)
想要提前了解细节的小伙伴可以可以去看阮一峰大大写的ES6 入门教程
结束!!
有任何问题欢迎👏👏👏留言讨论
下一章: 面试准备-函数