深入理解JS | 青训营笔记

58 阅读3分钟

基本概念

数据类型

JS中分为两种数据类型

  • 基本数据类型
    • string
    • number
    • null
    • symblol
    • undefined
    • bigInt
      • ES6为了保证大数精度而出的
    • Boolean
  • 引用数据类型
    • 数组
    • 函数

作用域

变量的 可访问性可见性

作用域主要分为以下三种:

  • 全局作用域
  • 函数作用域
  • 块级作用域(比如{}内的代码)

变量提升

  • var有变量提升
  • let、const没有变量提升,提前访问会报错
  • function函数可以先调用再定义
  • 赋值给变量的函数无法提前调用
console.log('company', company);
console.log('dep', dep);
console.log('myname', myname);
showInfo();
show(); //show is not a function

const company = "Bytedance";
let dep = "dazzlingwen";
var myname = 'wen';

function showInfo() {
    // console.log(company, dep, myname);
    console.log(myname);
}

var show = function () {
    console.log(myname);
}

show函数调用报错show is not a function的原因正是 赋值给变量的函数无法提前调用

show是作为一个变量接收了后面的匿名函数,所以不能提前调用,会报错

JS是怎么执行的

执行流程如下:

image.png

当JS引擎解析到可执行代码片段(通常是函数调用)的时候,就会先做一些执行前的准备工作,这个准备工作就叫做 执行上下文,也叫执行环境

分为:

  • 全局执行上下文
  • 函数执行上下文
  • Eval执行上下文

全局执行上下文:

代码开始执行时就会创建,将它压入执行栈的栈底,每个生命周期内只有一份(这里指的应该是浏览器页面的生命周期)

函数执行上下文:

当执行一个函数时,这个函数内的代码会被编译,生成变量环境、词法环境等,当函数执行结束的时候该执行环境从栈顶弹出

创建执行上下文的时候做了什么?

  • 绑定this
  • 创建词法环境
  • 创建变量环境

词法环境:

基于ECMAScript代码的词法嵌套结构来定义标识符和具体变量和函数的关联。

一个词法环境由环境记录器和一个可能的引用外部词法环境的空值组成

变量环境:

变量环境和词法环境的一个不同就是前者被用来存储函数声明和变量(let 和 const)绑定,而后者只用来存储 var 变量

Outer:

指向外部变量环境的一个指针

image.png

闭包

闭包的本质其实是一个函数,这个函数能够引用另一个函数作用域中的变量

比如:

function showName() {
    const company = "ByteDance";
    const dep = "bian";
    const name = "wen";
    console.log('company',company);

    return function (){
        console.log(dep);
        return name;
    }
}

const getName = showName();
console.log(getName());

输出:

image.png

我这边把最后两行改成这样试试输出

const getName = showName();
console.log(getName);

image.png

getName()相当于触发函数执行,而getName只是用变量接收了一个函数,所以打印出来的是[Function (anonymous)]

具体关于闭包更多的详见 当面试官让你说说闭包时

this

function showName(){
    console.log(this) //普通函数的this指向Windows
}

const persinObj = {
    name:'wen',
    age:'13',
    showName(){
        console.log(this.name)
    }
}

persinObj.showName(); //指向personObj

const getName = persinObj.showName;// 先赋值再调用拿到的就是undefined
getName();

下面举个new的例子

function showNameTwo(){
    this.name = 'dazzlingwen'
}
const getNameTwo = new showNameTwo();
console.log(getNameTwo)

new操作符做了什么?

  1. 创建临时对象
  2. 将this指向临时对象
  3. 执行构造函数
  4. 返回临时对象

垃圾回收

image.png

  1. 垃圾标记
  2. 对象复制
  3. 区域反转