JS直播总结 - 图1

浏览器渲染过程

问:在浏览器中,从输入UR到页面展示,这中间发生了什么?
如下图,一个浏览器有三个进程,浏览器进程、网络进程以及渲染进程。

image.png

  1. 网络进程中,发起url请求后有可能会进行一个重定向,然后读取响应头信息(这个信息会告诉浏览器我是HTML还是其他的谁),读取响应体数据(就是网页源代码)。
  2. 渲染过程

a. 处理HTML构建DOM树
b. 处理CSS构建CSSOM树
c. 将DOM和CSSOM合并成一个渲染树
d. 根据渲染树布局,计算每个节点几何信息
e. 将几何信息绘制在屏幕上

image.png

JavaScript实用技巧

var 和 let/const

  1. //我们想让这段代码隔0.1S打印0到9.但是结果打印了10个10
  2. for (var i = 0;i < 10;i++) {
  3. setTimeout(function(){
  4. console.log(i);},100);
  5. }
  6. //这是因为var会提升作用域,提升到全局。
  7. //setTimeout延迟100ms,但是for循环瞬间就执行了10次,所以每次当100ms到的时候,i已经等于10了
  8. var i = 0;
  9. for (i = 0;i < 10;i++) {
  10. setTimeout(function(){
  11. console.log(i);},100);
  12. }
  13. //换成ES6的let就可以了
  14. for (let i = 0;i < 10;i++) {
  15. setTimeout(function(){
  16. console.log(i);},100);
  17. }

实际上当使用 let 的时候,编译器会将 let 换成 var ,就是将 var 的作用域变成块作用域.

  1. //编译之后大概是这样
  2. function print(i){
  3. setTimeout(function(){
  4. console.log(i);},100);
  5. }
  6. for (var i = 0;i < 10;i++) {
  7. print(i);
  8. }

箭头函数

  1. 例子1 ```javascript for (let i = 0;i < 10;i++) { setTimeout(function(){ console.log(i);},1000); }

//使用箭头函数 for (let i = 0;i < 10;i++) { setTimeout(() => { console.log(i);},1000); }

  1. 2. 例子2
  2. ```javascript
  3. function abc(){
  4. console.log('abc');
  5. }
  6. //使用箭头函数
  7. const abc = () => {
  8. console.log('abc');
  9. }
  1. 例子3 ```javascript function sum(a,b) { return a+b; }

//使用箭头函数 const sum = (a,b) => { return a+b; }

//简化 const sum = (a,b) => a+b;

  1. <a name="u7tZy"></a>
  2. ### 回调函数 & Promise
  3. 比如给一个元素添加一个监听事件就是是一个回调函数。
  4. ```javascript
  5. //箭头函数就是回调函数
  6. document.addEventListener('click',()=>{
  7. });

为什么会出现回调函数?

  1. 理解同步和异步:

同步要等待其他事做完才会接着做下面的事,是按顺序执行(烧完水才能吃东西)
异步在做一件事的同时还可以做其他事(一边烧水,一边吃东西)

  1. 异步很方便,JS中通过使用回调函数来进行异步操作

例子:进入优课达网站要进行: 登录=>获取用户信息=>获取我的课程=>初始化


function login(){
  //模拟一下登录需要1s
  setTimeout(()=>{
    console.log('登录成功');
  },1000);
}

function getUserInfo(){
setTimeout(()=>{
    console.log('获取用户信息成功');
  },2000);
}

function getMyCourse(){
setTimeout(()=>{
    console.log('获取课程信息成功');
  },3000);
}

function init() {
  login();
  getUserInfo();
  getMyCourse();
  console.log('初始化成功');
}

init();

------------------
输出结果:
初始化成功
登录成功
获取用户信息成功
获取课程信息成功

这里就出现了问题,虽然是异步执行的(登录需要1s,所以就先去执行初始化了),但是还没有登录,也没有获取到用户信息如何初始化呢?这时就需要回调函数了。

//模拟回调函数callback 登录成功以后你再来调用我
function login(callback){
  //模拟一下登录需要1s
  setTimeout(()=>{
    console.log('登录成功');
    callback();
  },1000);
}
//获取到信息以后你再来调用我
function getUserInfo(callback){
setTimeout(()=>{
    console.log('获取用户信息成功');
  callback();
  },2000);
}
//获取到我的课程以后再来调用我
function getMyCourse(callback){
setTimeout(()=>{
    console.log('获取课程信息成功');
    callback();
  },3000);
}

function init() {
  /**
  login的回调函数调用getUserInfo,
  getUserInfo的回调函数调用getMyCourse,
  getMyCourse的回调里面初始化成功
  */
  login(()=>{
    getUserInfo(()=>{
      getMyCourse(()=>{
        console.log('初始化成功');
      });
    });
  });
}

init();
----------------------
输出结果:

登录成功
获取用户信息成功
获取课程信息成功
初始化成功

上面的写法结果是正确的,完全可。但是实际情况是每一个函数里面都有复杂的逻辑,而且还会有更多的请求函数,比如还要获取当前的打卡进度,获取课程进度等,那就需要一直回调,就变成了 回调地狱

ES6出现Promise 解决回调地狱

Promise 的出现就是为了去掉回调。

//promise会自动传一个resolve进来,函数执行完以后调用一下resolve就行了
function login(){
  return new Promise((resolve,reject) => {
    setTimeout(()=>{
      console.log('登录成功');
      resolve();
    },1000);
  });
}

function getUserInfo(){
  return new Promise((resolve,reject) => {
    setTimeout(()=>{
      console.log('获取用户信息成功');
      resolve();
    },2000);
  });
}

function getMyCourse(){
  return new Promise((resolve,reject) => {
    setTimeout(()=>{
      console.log('获取课程信息成功');
      resolve();
    },3000);
  });
}

function init() {
  //先登录然后执行一个函数,这个函数里面执行getUserInfo()
  //然后再执行个函数里面执行getMyCourse
  login()
   .then(()=>{
    return getUserInfo();
    })
   .then(() => {
    return getMyCourse();
    })
    .then(() =>{
    console.log('初始化成功');
  });
}

//简化init()
function init() {
  login()
    .then(getUserInfo)//这里注意传进去的不是函数而是函数执行的结果
    .then(getMyCourse)
    .then(() =>{
    console.log('初始化成功');
  });
}

init();
----------------------
输出结果:

登录成功
获取用户信息成功
获取课程信息成功
初始化成功

Promise 的用法和 fetch 很像。其实 fetch 本身就是一个 Promise ,只有 promise 才有 .then 这个方法。

ES7 async & await

ES7用 asyncawait 又做了简化, await 后面接的一定是 promise 的东西。

//异步
async function init() {
  //等待
  await login();
  await getUserInfo();
  await getMyCourse();
  console.log('初始化成功');

}