变量声明提前和函数声明提前

476 阅读2分钟

JavaScript数据类型分两种:

基本数据类型:null undefined Boolean Number String

按值访问,可以操作保存在变量中的实际的值。

引用数据类型:Object

引用类型的值是保存在内存中的对象,JavaScript不允许直接访问内存中的位置,也就是说不能直接操作对象的内存空间。实际上是在操作对象的引用而不是实际的对象。

引用类型的值是按引用访问的。这种说法不严谨,当复制保存着对象的某个变量时,操作的是对象的引用。在为对象添加属性时,操作的是实际的对象。

在全局执行上下文中,this总是指向全局对象,例如浏览器环境下this指向window对象。

在函数执行上下文中,this的值取决于函数的调用方式,如果被一个对象调用,那么this指向这个对象。否则this一般指向全局对象window或者undefined(严格模式)。

只有函数声明格式的函数才会存在函数声明提前,比如函数表达式、构造函数都不存在函数声明提前

函数声明方式,存在声明提前,在创建阶段它就是一个明确的函数了,

function func() {}

函数表达式创建的函数,不存在声明提前

var func = function(){}

使用var声明,在创建阶段会给一个undefined作为初始值

  • let和const,它们在创建时,是没有初始值的,状态为uninitialized(未初始化),在声明它之前使用它,是不合法的,对应了ES6中暂时性死域的概念

  • 暂时性死区的本质是,只要进入当前作用域,所要使用的变量就已经存在,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。

    // 第一种情况 if(true){
    // console.log(tmp);
    let tmp;
    } // ReferenceError: Cannot access 'tmp' before initialization // 第二种情况,暂时性死区 if(true){
    tmp = 2;
    let tmp;
    } // Uncaught ReferenceError: Cannot access 'tmp' before initialization

    if(true){
    let tmp;
    console.log(tmp); }// undefined

let const在同一作用域不能重复声明

function fn(){
    var a = 1;
    let a = 2;
}
fn();

// SyntaxError: Identifier 'a' has already been declared

重点:同一作用域下,函数会首先被提升,然后是变量声明提前。声明提前,赋值原地不变

函数声明提前,变量声明也提前,到底谁会更提的更前?假设两者都用的同一命名声明,到底最后会输出啥

console.log(a); // ?
a(); //?
var a =3;
function a(){    
    console.log(10);
}
console.log(a); //?
a = 6;
a(); //?

输出结果:

ƒ a(){ console.log(10); }

10

3

Uncaught TypeError: a is not a function

函数声明类声明之间的一个重要区别在于, 函数声明会提升,类声明不会。

let p = new Rectangle(); // ReferenceError

class Rectangle {}