深入理解JavaScript | 青训营笔记

67 阅读2分钟

深入理解 JS

作用域

静态作用域能够预测代码在执行过程中如何查找标识符

全局作用域

var a = 'a'
function fun()
{
    console.log(a);
}
fun()

函数作用域

var a = 'a';
function fun()
{
    a = 'b';
    console.log(a);
}
fun()

块级作用域

{
    const a = 'a';
    console.log(1,a);
}
console.log(2,a);

var

提升地址

var company = undefined;
console.log(company);
company = "Bytedance";

函数

提升函数变量

showName()
function showName(){
    console.log('zq'); //zq
}

以下方法会报错 func is not a function ,var提升变量func并赋值为undefined

func();
var func = showName;
function showName(){
    console.log('zq')
}

总结:

  1. var 有变量提升
  2. let、const没有变量提升,提前访问会报错
  3. function 函数可以先调用再定义
  4. 赋值给变量的函数无法提前调用

执行上下文

所有通过var定义的全局变量和函数都会成为window对象的属性和方法。上下文在其所有代码都执行完毕后会被销毁,包括定义 在它上面的所有变量和函数(全局上下文在应用程序退出前才会被销毁,比如关闭网页或退出浏览器)。

上下文中的代码在执行的时候,会创建变量对象的一个作用域链(scope chain)。这个作用域链决定 了各级上下文中的代码在访问变量和函数时的顺序。

每个上下文都可以 到上一级上下文中去搜索变量和函数,但任何上下文都不能到下一级上下文中去搜索。

闭包

闭包指的是那些引用了另一个函数作用域中变量的函数,通常是在嵌套函数中实现的。

概念:一个函数对周围状态的引用捆绑在一起,内层函数中访问到其外层函数的作用域

简单理解:闭包 = 内层函数 + 引用的外层函数变量

满足闭包的 4 个条件:

  1. 有函数嵌套
  2. 内部函数引用外部作用域的变量参数
  3. 返回值是函数
  4. 创建一个对象函数,让其长期驻留

实现函数没调用一次变量减一

function fa(){
    let a = 10;
    function fb(){
        a--;
        console.log(a);
    }
    return fb;
}
var fm = fa();
fm =  null;

this

  1. 普通函数的this指向window

    function showName(){
        console.log(this); //window
    }
    
  2. 对象调用指向对象。先赋值再调用,看调用的地方

    const name = 11;
    const obj = {
        name:'zq',
        showName(){
            console.log(this.name); //'zq'
        }
    }
    obj.showName();
    

    若想改变this指向则使用applycallbind

    const obj1 = {
        name:'zq',
        showName(){
            console.log(this.name);//'zq'
        }
    }
    const obj1 = {
        name:'bytedance'
    }
    obj.showName.apply(obj1);//'bytedance'
    
    const personObj = {
        name:'zhangqi',
        dep:'边缘云',
        showName(){
            console.log(this.name);
        }
    }
    personObj.showName(); //'zhangqi'
    const getName = personObj.showName
    getName()//undefined
    
  3. 创建临时对象;将this指向临时对象;执行构造函数;返回临时对象

    function ShowName(){
        this.name = "zhangqi";
    }
    const getName = new ShowName()
    console.log(getName);//ShowName{name:'zhangqi'}
    

宏任务、微任务

执行过程:

  1. 同步代码(JS执行栈/回调栈)

  2. 微任务的异步代码(JS引擎)

    • process.nextTick(node)
    • Promise.then() catch()
    • Async/Await
    • Object.observe
  3. 宏任务的异步代码(宿主环境)

    • script(代码块)
    • setTimeout/setInterval 定时器
    • setImmedia 定时器