面试准备-声明

201 阅读5分钟

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点:

  1. var的声明虽然提前了,但是赋值操作依然是在原代码行执行
  2. 函数作用域可以访问外层作用域中声明的变量,反过来是不行的!
  3. 虽然存在声明提升,但是使用没有声明的变量是会抛出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 入门教程

结束!!

有任何问题欢迎👏👏👏留言讨论

下一章: 面试准备-函数