SOURCE

/**
 * “变量提升”意味着变量和函数的声明会在物理层面移动到代码的最前面,但这么说并不准确。
 * 变量和函数声明在代码里的位置是不会动的,而是在编译阶段被放入内存中。
 * 
 * 函数和变量相比,会被优先提升。这意味着函数会被提升到更靠前的位置。
 * 
 * 用 var 声明的变量的作用域是它当前的执行上下文,
 * 它可以是嵌套的函数,或者对于声明在任何函数外的变量来说是全局。
 * 没用 var 声明的变量可以用 delete 对目标对象上删除,反之不行
 */

console.log('----------------------- 变量提升 -----------------------')
// 变量提升
console.log(name1 + '')
fn()

var name1 = 'Tom';

(function () {
    console.log(name1 + '')
    var name1 = 'Lis'
    console.log(name1 + '')
})()

function fn() {
    console.log(fn)
}

console.log(name1 + '')

console.log(fn1)
var fn1 = function() {
    console.log(fn1)
}

/**
 * 对应的伪代码
 * 变量提升是相对于作用于而言的,
 * 函数的提升在变量前面
 * 函数表达式不会被提升
    var fn
    fn = () {
        console.log(fn)
    }
    var name1
    console.log(name1 + '')
    fn()

    name1 = 'Tom'

    ;(function() {
        var name1
        console.log(name1 + '')
        name1 = 'Lis'
        console.log(name1 + '')
    })()

    console.log(name1 + '')

    fn1()
    var fn1 = function() {
        console.log(fn1)
    }
 * 
 */




console.log('----------------------- 作用域 -----------------------')
// 作用域
var xx = 0;
var zz = 1;

function f() {
    // 当赋值给未声明的变量, 则执行赋值后, 该变量会被隐式地创建为全局变量(它将成为全局对象的属性)
    // xx 函数作用域中
    var xx = xxx = 1;
    zz = 2
    console.log(xx, xxx) // 1 1
}
f();

console.log(xx, xxx, zz); // 0 1 2

var yy = 0

if (true) {
    var yy = 1  // 覆盖全局的
}

console.log(yy)

for (var i = 0; i < 2; i++) { }

console.log(i)

// var 声明的变量只有函数作用域




console.log('----------------------- 作用域链 -----------------------')
// 作用域链
var x = 0;  // x是全局变量,并且赋值为0。

console.log(typeof z); // undefined,因为z还不存在。

function a() { // 当a被调用时,
    var y = 2;   // y被声明成函数a作用域的变量,然后赋值成2。

    console.log(x, y);   // 0 2 

    function b() {       // 当b被调用时,
        x = 3;  // 全局变量x被赋值为3,不生成全局变量。
        y = 4;  // 已存在的外部函数的y变量被赋值为4,不生成新的全局变量。
        z = 5;  // 创建新的全局变量z,并且给z赋值为5。 
    }         // (在严格模式下(strict mode)抛出ReferenceError)

    b();     // 调用b时创建了全局变量z。
    console.log(x, y, z);  // 3 4 5
}

a();                   // 调用a时同时调用了b。
console.log(x, z);     // 3 5
console.log(typeof y); // undefined,因为y是a函数的本地(local)变量。




console.log('----------------------- 给匿名函数赋予一个名字 -----------------------')
// 给匿名函数赋予一个名字以后,改名字只读不能写
// 然后再在这个函数里面对这个名字进行操作
// 是会被自动忽略的
var aa = 1
var bb = 1
function cc() {
    cc = 3
    console.log(cc)
}
cc();

(function bb() {
    aa = bb = 2
    console.log(bb)
})()

console.log(aa)
console.log(bb)
console 命令行工具 X clear

                    
>
console