es6基础知识巩固

本来给予公司很大期盼,结果一年多还是工资拖拖拉拉几个月发一次。现在开始准备一下了,俗话说:不管在哪里还是自己靠得住。

类型转换

数据类型

js基本类型:undefined、null、Boolean、String、Number、Symbol、BigInt(es10)

js引用类型:Object

装箱与拆箱

  • 包装类(对象引用类型)和原始值之间的相互转换,值类型->包装类(装箱),包装类->值类型 (拆箱)。
  • 值类型在栈内存中存储,引用类型在堆内存中存储。
  • js作为面向对象语言在类型方面做出妥协,为部分基础类型系统中的"值类型"设定对应的包装类,通过包装类,将"值类型数据"作为对象来处理。
  • 显式装箱:
ini 复制代码
 const a = new String("d");
 const b = Number(1)
  • 隐式装箱
ini 复制代码
    const a = "aaa";
    a.substring(0, 1);
    // 相当于
    const a = new String("aaa");
    a.substing(0, 1);

部分特殊例子

scss 复制代码
    if("0") console.log("123");//123
    ({}) + 1 = // [object Object]1' //加号与-/*符号不一样
    [] == ![] // true 先执行![] = false然后false转化为零 ,然后[]转为0,比布尔类型比较会先转换为数字

instanceof和-typeof实现

  • instanceof主要用于判断对象类型
ini 复制代码
function new_instance_of(leftVaule, rightVaule) { 
    let rightProto = rightVaule.prototype; // 取右表达式的 prototype 值
    leftVaule = leftVaule.__proto__; // 取左表达式的__proto__值
    while (true) {
    	if (leftVaule === null) {
            return false;	
        }
        if (leftVaule === rightProto) {
            return true;	
        } 
        leftVaule = leftVaule.__proto__ 
    }
}
  • typeof 主要判断基础类型,typeof原理: 不同的对象在底层都表示为二进制,在Javascript中二进制前(低)三位存储其类型信息。000: 对象、010: 浮点数、100:字符串、 110: 布尔、 1: 整数。

  • 一般判断对象可以简单使用Object.prototype.toString.call(xxx);call的作用是Object指向当前对象。

函数进阶

arguments

arguments 是一个对应于传递给函数的参数的类数组对象, 它只定义在函数体内。

  • arguments.callee():在此调用函数本身,用于递归,后来废弃因为体积较大。
  • 箭头函数没有arguments。

call、apply、bind

call和apply作用一样,只是传参方式不同,会执行函数,bind是返回一个函数。

js执行过程

  1. v8引擎初始化执行环境:堆和栈、全局上下文、全局作用域、事件循环系统、其他 (上下文:包含vo变量存储 + 作用域链 + this指向)。
  2. 解析阶段
  • 创建一个全局对象 GO/window(全局作用域)

  • 词法分析。词法分析就是将我们写的代码块分解成词法单元。

  • 检查语法是否有错误。语法分析是将词法单元流(数组)转换成一个由元素逐级嵌套所组成的代表了程序语法结构的树。这个树被称为"抽象语法树"(Abstract Syntax Tree,AST)。 并检查你的代码有没有什么低级的语法错误,如果有,引擎会停止执行并抛出异常。

  • 给全局对象 GO 赋值(GO/VO 中不止包括变量自身,还包含其他的上下文等)

  • 收集全局定义的变量以及函数,这时会产生变量提升

  1. 执行阶段 生成全局上下文入栈->遇到函数执行时候会生成函数执行上下文并入栈->创建上下文时词法环境变量环境被创建、this指向确定->依次执行栈。
  2. 回收阶段
  • 什么是数据垃圾:没有被引用的变量
  • 垃圾回收算法:从根节点(window、dom、栈变量)出发遍历能遍历到的就是可达的,不可以达将被标记->回收不大达的数据->整理内存
  • 分代回收:一些对象长久存在一些对象刚执行就被回收,所有变量被分这两种对象对应不同的回收策略,所以,V8 把堆分为新生代和老生代两个区域, 新生代中存放临时对象,老生代中存放持久对象。
  • 主垃圾回收器:主要负责老生代回收,使用标记清除算法清除数据,多次清除后,会按序整理空间。
  • 副垃圾回收器:分为对象区和空闲区,按照标记清除算法清除数据复制后到空闲区,在调换对象区和空闲区。

部分es6方法实现

async awiat

实现思路:利用Generator函数,把异步函数和其他代码分割成一个单独的函数,然后用这些函数构成生成器。再利用一个新的函数返回promise的结果并在函数中递归执行生成器。

javascript 复制代码
function asyncToGenerator(generatorFunc) {
  // 返回的是一个新的函数
  return function() {
  
    // 先调用generator函数 生成迭代器
    // 对应 var gen = testG()
    const gen = generatorFunc.apply(this, arguments)

    // 返回一个promise 因为外部是用.then的方式 或者await的方式去使用这个函数的返回值的
    // var test = asyncToGenerator(testG)
    // test().then(res => console.log(res))
    return new Promise((resolve, reject) => {
    
      // 内部定义一个step函数 用来一步一步的跨过yield的阻碍
      // key有next和throw两种取值,分别对应了gen的next和throw方法
      // arg参数则是用来把promise resolve出来的值交给下一个yield
      function step(key, arg) {
        let generatorResult
        
        // 这个方法需要包裹在try catch中
        // 如果报错了 就把promise给reject掉 外部通过.catch可以获取到错误
        try {
          generatorResult = gen[key](arg)
        } catch (error) {
          return reject(error)
        }

        // gen.next() 得到的结果是一个 { value, done } 的结构
        const { value, done } = generatorResult

        if (done) {
          // 如果已经完成了 就直接resolve这个promise
          // 这个done是在最后一次调用next后才会为true
          // 以本文的例子来说 此时的结果是 { done: true, value: 'success' }
          // 这个value也就是generator函数最后的返回值
          return resolve(value)
        } else {
          // 除了最后结束的时候外,每次调用gen.next()
          // 其实是返回 { value: Promise, done: false } 的结构,
          // 这里要注意的是Promise.resolve可以接受一个promise为参数
          // 并且这个promise参数被resolve的时候,这个then才会被调用
          return Promise.resolve(
            // 这个value对应的是yield后面的promise
            value
          ).then(
            // value这个promise被resove的时候,就会执行next
            // 并且只要done不是true的时候 就会递归的往下解开promise
            // 对应gen.next().value.then(value => {
            //    gen.next(value).value.then(value2 => {
            //       gen.next() 
            //
            //      // 此时done为true了 整个promise被resolve了 
            //      // 最外部的test().then(res => console.log(res))的then就开始执行了
            //    })
            // })
            function onResolve(val) {
              step("next", val)
            },
            // 如果promise被reject了 就再次进入step函数
            // 不同的是,这次的try catch中调用的是gen.throw(err)
            // 那么自然就被catch到 然后把promise给reject掉啦
            function onReject(err) {
              step("throw", err)
            },
          )
        }
      }
      step("next")
    })
  }
}

promise

api:

  1. Promise.all(promises) ------ 等待所有 promise 都 resolve 时,返回存放它们结果的数组。如果给定的任意一个 promise 为 reject,那么它就会变成 Promise.all 的 error,所有其他 promise 的结果都会被忽略。

  2. Promise.allSettled(promises)(ES2020 新增方法)------ 等待所有 promise 都 settle 时,并以包含以下内容的对象数组的形式返回它们的结果:

    • status: "fulfilled""rejected"
    • value(如果 fulfilled)或 reason(如果 rejected)。
  3. Promise.race(promises) ------ 等待第一个 settle 的 promise,并将其 result/error 作为结果返回。

  4. Promise.any(promises)(ES2021 新增方法)------ 等待第一个 fulfilled 的 promise,并将其结果作为结果返回。如果所有 promise 都 rejected,Promise.any 则会抛出 AggregateError 错误类型的 error 实例。

  5. Promise.resolve(value) ------ 使用给定 value 创建一个 resolved 的 promise。

  6. Promise.reject(error) ------ 使用给定 error 创建一个 rejected 的 promise。 new Promise 接收函数会立即执行。

promise实现:xxx

事件循环

执行宏任务,然后执行该宏任务产生的微任务,若微任务在执行过程中产生了新的微任务,则继续执行微任务,微任务执行完毕后,再回到宏任务中进行下一轮循环。

javascript 复制代码
async function async1(){
    console.log('async1 start')
    await async2()
    console.log('async1 end')
}
// 相当于
console.log('async1 start')
async2()
promise.then(() => 
 console.log('async1 end')
)


retrun new Promise() 相当雨二个then

引用

juejin.cn/post/723546... juejin.cn/post/693783... juejin.cn/post/684490... juejin.cn/post/684490...

相关推荐
知其然亦知其所以然几秒前
MySQL8.x 面试高频题:为什么一定要有主键?99%的人答不全
后端·mysql·面试
程序员清风19 分钟前
快手二面:Redisson公平锁用用过吗?他的实现原理是什么样子的?
java·后端·面试
PuddingSama41 分钟前
Android 高级绘制技巧: BlendMode
android·前端·面试
PineappleCoder1 小时前
面试官你好,请您听我“编解”!!!
前端·算法·面试
moonlifesudo1 小时前
1.Deque和Stack的区别以及ArrayDeque、LinkedList这两个类的不同
面试
前端小巷子2 小时前
JS 打造仿腾讯影视轮播导航
前端·javascript·面试
大模型真好玩2 小时前
大模型工程面试经典(五)—大模型微调与RAG该如何选?
人工智能·面试·deepseek
绝无仅有2 小时前
面试之MySQL基础和事务实战经验总结与分享
后端·面试·github
绝无仅有3 小时前
面试经验之MySQL 锁与索引实战总结分享
后端·面试·github
在未来等你6 小时前
Elasticsearch面试精讲 Day 13:索引生命周期管理ILM
大数据·分布式·elasticsearch·搜索引擎·面试