前端学习笔记

81-89JS函数变量作用域和预解析

2019-05-06  本文已影响1人  饥人谷_island
  1.在JavaScript中定义变量有两种方式
    ES6之前: var 变量名称;
    ES6开始: let 变量名称;
    */
    // 2.两种定义变量方式的区别
    // 2.1是否能够定义同名变量
    /*
    1.通过var定义变量,可以重复定义同名的变量,并且后定义的会覆盖先定义的
    var num = 123;
    var num = 456;
    console.log(num);

    2.2如果通过let定义变量,  "相同作用域内"不可以重复定义同名的变量
    let num = 123;
    let num = 456; // 报错
    */

    // 2.2是否能够先使用后定义
    /*
    2.3通过var定义变量, 可以先使用后定义(预解析)
    console.log(num);
    var num = 123;

    2.4通过let定义变量, 不可以先使用再定义(不会预解析)
    console.log(num); // 报错
    let num = 123;
    */

    // 2.3是否能被{}限制作用域
    /*
    2.5无论是var还是let定义在{}外面都是全局变量
    var num = 123;
    let num = 123;

    2.6将var定义的变量放到一个单独的{}里面, 还是一个全局变量
    {
        var num = 123;
    }
    console.log(num);  //不会报错

    2.7将let定义的变量放到一个单独的{}里面, 是一个局部变量
    {
        let num = 123;
    }
    console.log(num);  //会报错
    */

    /*
    1.在JavaScript中{}外面的作用域, 我们称之为全局作用域

    2.在JavaScript中函数后面{}中的的作用域, 我们称之为"局部作用域"
    3.在ES6中只要{}没有和函数结合在一起, 那么应该"块级作用域"
    4.块级作用域和局部作用域区别
    4.1在块级作用域中通过var定义的变量是全局变量
    4.2在局部作用域中通过var定义的变量是局部变量

    5.无论是在块级作用域还是在局部作用域, 省略变量前面的let或者var就会变成一个全局变量
    */
    /*
    {
        // 块级作用域
    }
    if(false){
        // 块级作用域
    }
    while (false){
        // 块级作用域
    }
    for(;;){
        // 块级作用域
    }
    do{
        // 块级作用域
    }while (false);
    switch () {
        // 块级作用域
    }
    function say() {
        // 局部作用域
    }
    */

    /*
    {
        // 块级作用域
        var num = 123; // 全局变量
    }
    console.log(num);

    function test() {
        var value = 666; // 局部变量
    }
    test();
    console.log(value);
    */
    /*
    if(true){
        var num = 666;
    }
    console.log(num);
    */

    /*
    {
        // var num = 678; // 全局变量
        // let num = 678; // 局部变量
        num = 678; // 全局变量
    }
    console.log(num);
    */
    function test() {
        // var num = 123; // 局部变量
        // let num = 123; // 局部变量
        num = 123; // 全局变量
    }
    test();
    console.log(num);

    // 1.找出下列哪些是全局变量,哪些是局部变量
    /*
    var num1 = 123; // 全局变量
    function test() {
        var num2 = 456; // 局部变量
    }
    {
        var num3 = 789; // 全局变量
    }
    function test() {
        num4 = 666; // 全局变量
    }
    */

    // 2.找出下列哪些是全局变量,哪些是局部变量
    /*
    let num1 = 123; // 全局变量
    function test() {
        let num2 = 456; // 局部变量
    }
    {
        let num3 = 789; // 局部变量
    }
    function test() {
        num4 = 666; // 全局变量
    }
    */

    // 3.下列代码运行是否会报错
    /*
    var num = 123;
    var num = 456; // 不会报错
    */
    /*
    {
       var num = 123;
        {
            var num = 456; // 不会报错
        }
    }
    */
    /*
    console.log(num); // 不会报错
    var num = 123;
    */

    // 4.下列代码运行是否会报错
    /*
    let num = 123;
    let num = 456; // 会报错
    */
    /*
    {
       let num = 123;
        {
        // 注意点: 在不同的作用域范围内, 是可以出现同名的变量的
            let num = 456; // 不会报错
        }
    }
    */
    /*
    console.log(num); // 会报错
    let num = 123;
    */

    // 5.下列代码运行是否会报错
    /*
    // 注意点: 只要出现了let, 在相同的作用域内, 就不能出现同名的变量
    let num = 123;
    var num = 456; // 会报错
    */
    /*
    var num = 123;
    let num = 456; // 会报错
    */

   注意点: 初学者在研究"作用域链"的时候最好将ES6之前和ES6分开研究

    1.需要明确:
    1.ES6之前定义变量通过var
    2.ES6之前没有块级作用域, 只有全局作用域和局部作用域
    3.ES6之前函数大括号外的都是全局作用域
    4.ES6之前函数大括号中的都是局部作用域

    2.ES6之前作用域链
    1.1.全局作用域我们又称之为0级作用域
    2.2.定义函数开启的作用域就是1级/2级/3级/...作用域
    2.3.JavaScript会将这些作用域链接在一起形成一个链条, 这个链条就是作用域链
      0  --->  1 ---->  2  ---->  3 ----> 4
    2.4.除0级作用域以外, 当前作用域级别等于上一级+1

    3.变量在作用域链查找规则
    3.1先在当前找, 找到就使用当前作用域找到的
    3.2如果当前作用域中没有找到, 就去上一级作用域中查找
    3.3以此类推直到0级为止, 如果0级作用域还没找到, 就报错
    */

    // 全局作用域 / 0级作用域
    // var num = 123;
    function demo() {
        // 1级作用域
        // var num = 456;
        function test() {
            // 2级作用域
            // var num = 789;
            console.log(num);
        }
        test();
    }
    demo();

   注意点: 初学者在研究作用域的时候最好将ES6之前和ES6分开研究

    1.需要明确:
    1.ES6定义变量通过let
    2.ES6除了全局作用域、局部作用域以外, 还新增了块级作用域
    3.ES6虽然新增了块级作用域, 但是通过let定义变量并无差异(都是局部变量)

    2.ES6作用域链
    1.1.全局作用域我们又称之为0级作用域
    2.2.定义函数或者代码块都会开启的作用域就是1级/2级/3级/...作用域
    2.3.JavaScript会将这些作用域链接在一起形成一个链条, 这个链条就是作用域链
      0  --->  1 ---->  2  ---->  3 ----> 4
    2.4.除0级作用域以外, 当前作用域级别等于上一级+1

    3.变量在作用域链查找规则
    3.1先在当前找, 找到就使用当前作用域找到的
    3.2如果当前作用域中没有找到, 就去上一级作用域中查找
    3.3以此类推直到0级为止, 如果0级作用域还没找到, 就报错
    */

    // 全局作用域 / 0级作用域
    // let num = 123;
    {
        // 1级作用域
        // let num = 456;
        function test() {
            // 2级作用域
            // let num = 789;
            console.log(num);
        }
        test();
    }

    1.什么是预解析?
    浏览器在执行JS代码的时候会分成两部分操作:预解析以及逐行执行代码
    也就是说浏览器不会直接执行代码, 而是加工处理之后再执行,
    这个加工处理的过程, 我们就称之为预解析

    2.预解析规则
    2.1将变量声明和函数声明提升到当前作用域最前面
    2.2将剩余代码按照书写顺序依次放到后面

    3.注意点
    通过let定义的变量不会被提升(不会被预解析)
    
    
    // 预解析之前
    console.log(num); //undefined
    var num = 123;
    // 预解析之后
    var num;
    console.log(num);
    num = 123;
    
    
    // 不会预解析之前
    console.log(num); // 报错
    let num = 456;
    

    // ES6之前定义函数的格式
    
    console.log(say);
    say();
    // ES6之前的这种定义函数的格式, 是会被预解析的, 所以可以提前调用
    function say() {
        console.log("hello it666");
    }
   
    
    // 预解析之后的代码
    function say() {
        console.log("hello it666");
    }
    say();
    

    
    console.log(say);
    say(); // say is not a function
    // 如果将函数赋值给一个var定义的变量, 那么函数不会被预解析, 只有变量会被预解析
    var say = function() {
        console.log("hello itzb");
    }
    
    
    var say; //undefined
    say();
    say = function() {
        console.log("hello itzb");
    }
    

    // ES6定义函数的格式
    say(); // say is not defined
    let say = () => {
        console.log("hello itzb");
    }

    // 1.下列程序的执行结果是什么?
    var num = 123;
    fun();
    function fun() {
        console.log(num);
        var num = 666;
    }
    
    var num;
    function fun() {
       var num;
       console.log(num); // undefined
       num = 666;
    }
    num = 123;
    fun();

  // 1.下列程序的执行结果是什么?
    var a = 666;
    test();
    function test() {
        var b = 777;
        console.log(a);
        console.log(b);
        console.log(c);
        var a = 888;
        let c = 999;
    }
    
    var a;
    function test() {
       var b;
       var a;
       b = 777;
        console.log(a); // undefined
        console.log(b); // 777
        console.log(c); // 报错
        a = 888;
        let c = 999;
    }
    a = 666;
    test();
    */

    // 1.下列程序的执行结果是什么?
    // 在ES6之前没有块级作用域, 并且没有将这两个函数定义到其它的函数中,
    // 所以这两个函数应该属于全局作用域
    // 注意点:
    // 1.在高级浏览器中, 不会对{}中定义的函数进行提升
    // 2.只有在低级浏览器中, 才会按照正常的方式解析
    if(true){
        function demo() {
            console.log("hello demo1111111111");
        }
    }else{
        function demo() {
            console.log("hello demo2222222222");
        }
    }
    demo();
    
    function demo() {
        console.log("hello demo1111111111");
    }
    function demo() {
        console.log("hello demo2222222222");
    }
    if(true){}else{}
    demo();
    */

    // 1.下列程序的执行结果是什么?
    // 注意点: 如果变量名称和函数名称同名, 那么函数的优先级高于变量
    // 一定要记住, 在企业开发中千万不要让变量名称和函数名称重名
    console.log(value); // 会输出函数的定义
    var value = 123;
    function value() {
        console.log("fn value");
    }
    console.log(value); // 会输出123
    

    function value() {
        console.log("fn value");
    }
    console.log(value);
    var value;
    value = 123;
    console.log(value);
    */
上一篇下一篇

猜你喜欢

热点阅读