前端JavaScript高級面試技巧[1]

第1章 課程介紹

1-1 導(dǎo)學(xué)

課程概述

  • 做什么烦绳?— 講解前端 JS 高級面試題
  • 哪些部分澄港?— 高級基礎(chǔ), 框架原理, app混合開發(fā)
  • 技術(shù)劳景?— JS誉简、ES6、虛擬DOM枢泰、vue描融、React、hybrid

知識(shí)點(diǎn)介紹

  • 基礎(chǔ)知識(shí):ES6 常用語法衡蚂、原型高級應(yīng)用窿克、異步全面講解
  • 框架原理:虛擬 DOM、MVVM vue毛甲、組件化 React
  • 混合開發(fā):hybrid年叮、hybrid vs H5、前端客戶端通訊

課程安排

  • 高級基礎(chǔ)
    1. ES6 常用語法:Class Module Promise 等
    2. 原型高級應(yīng)用:結(jié)合 jQuery 和 zepto 源碼
    3. 異步全面講解:從原理到 jQuery 再到 Promise
  • 框架原理
    1. 虛擬 DOM:存在價(jià)值玻募,如何使用只损,diff 算法
    2. vue:MVVM,vue 響應(yīng)式七咧、模板解析跃惫、渲染
    3. React:組件化,JSX艾栋,vdom爆存,setState
    4. 對比:有主見,自圓其說
  • App混合開發(fā)
    1. hybrid:基礎(chǔ)蝗砾、和 h5 對比先较,上線流程
    2. 通訊:通訊原理,JS-Bridge 封裝

講授方式

  • 先出面試題悼粮,帶領(lǐng)大家思考
  • 通過題目引出知識(shí)點(diǎn)闲勺,擴(kuò)充講解知識(shí)體系
  • 最后通過學(xué)到的知識(shí)點(diǎn),解答題目

課程收獲

  • 從深度和廣度都擴(kuò)充了自己的知識(shí)體系
  • 學(xué)會(huì)如何高效學(xué)習(xí)
  • 深入理解常用框架的實(shí)現(xiàn)原理和 hybrid 應(yīng)用

1-2 課程重要提示

1-3 架構(gòu)-題目

ES6

模塊化的使用和編譯環(huán)境扣猫?

Class 與 JS 構(gòu)造函數(shù)的區(qū)別菜循?

Promise 的用法?

ES6 其他常用功能苞笨?

異步

什么是單線程债朵,和異步有什么關(guān)系子眶?

什么是 event-loop?

目前 JS 解決異步的方案有哪些序芦?

如果只用 jquery 如何解決異步臭杰?

Promise 的標(biāo)準(zhǔn)?

async/await 的使用谚中?

原型

原型如何實(shí)際應(yīng)用渴杆?

原型如何滿足擴(kuò)展?

vdom

什么是 vdom宪塔,為何要用 vdom磁奖?

vdom如何使用,核心函數(shù)有哪些某筐?

了解 diff 算法嗎比搭?

MVVM

之前使用 jquery 和現(xiàn)在使用 Vue 或 React 框架的區(qū)別?

你如何理解MVVM南誊?

Vue 如何實(shí)現(xiàn)響應(yīng)式身诺?

Vue 如何解析模版?

介紹 Vue 的實(shí)現(xiàn)流程抄囚?

組件化

對組件化的理解霉赡?

JSX 是什么?

JSX 和 vdom 什么關(guān)系幔托?

簡述 React 的 setState穴亏?

簡述自己如何比較 React 和 Vue?

hybrid

hybrid 是什么重挑,為何要用hybrid嗓化?

hybrid 如何更新上線?

hybrid 和 h5 有何區(qū)別谬哀?

JS 如何與客戶端通信蟆湖?

第2章 ES6 語法

2-1 開始

ES6

  • 開發(fā)環(huán)境已經(jīng)普及使用
  • 瀏覽器環(huán)境卻支持不好(需要開發(fā)環(huán)境編譯)
  • 內(nèi)容很多,重點(diǎn)了解常用語法
  • 面試:開發(fā)環(huán)境的使用 + 重點(diǎn)語法的掌握

題目

  • ES6 模塊化如何使用玻粪,開發(fā)環(huán)境如何打包?
  • Class 和普通構(gòu)造函數(shù)有何區(qū)別诬垂?
  • Promise 的基本使用和原理劲室?
  • 總結(jié)一下 ES6 其他常用功能?

2-2 模塊化

【題目】

ES6 模塊化如何使用结窘,開發(fā)環(huán)境如何打包很洋?

【知識(shí)點(diǎn)】

1. 模塊化的基本語法

  • export 語法
// util1.js
export default {
  a: 100
};

// util2.js
export function fn1() {
  alert('fn1');
};
export function fn2() {
  alert('fn2');
};
  • import 語法
// index.js
import util1 from './util1.js';
import { fn1, fn2 } from './util2.js';

console.log(util1);
fn1();
fn2();

2. 開發(fā)環(huán)境配置

babel

  • 安裝 babel
1. 電腦有 node 環(huán)境,運(yùn)行 npm init
2. npm install --save-dev babel-core babel-preset-es2015 babel-preset-latest
3. 創(chuàng)建 .babelrc 文件隧枫,輸入以下內(nèi)容:
    { 
        "presets": ["es2015", "latest"],
        "plugins": []
    }
4. sudo npm install -g babel-cli
5. babel --version
  • 使用 babel
1. 創(chuàng)建:./src/index.js
2. 內(nèi)容:[1, 2, 3].map(item => item + 1);
3. 運(yùn)行:babel ./src/index.js

webpack

1. npm install webpack webpack-cli babel-loader@^7.1.2 --save-dev
2. 配置 webpack.config.js谓苟,輸入以下內(nèi)容:
    module.exports = { 
        entry: './src/index.js',
        output: { 
          path: __dirname,
          filename: './build/bundle.js'
        },
        module: { 
          rules: [{
            test: /\.js?$/,
            exclude: /{node_modules}/,
            loader: 'babel-loader'
          }]
        }
    }
3. 配置 package.json 中的 scripts
    "scripts": {
        "start": "webpack"
    }
4. 運(yùn)行 npm start
5. 創(chuàng)建:index.html
    <script type="text/javascript" src="./build/bundle.js"></script>
6. http-server -p 8881
7. 訪問 http://localhost:8881/index.html

rollup

  • 安裝 rollup

https://www.rollupjs.com/guide/tutorial rollup 中文網(wǎng)

1. npm init
2. npm i rollup rollup-plugin-node-resolve rollup-plugin-babel@^3.0.3 babel-plugin-external-helpers babel-preset-latest babel-core --save-dev
3. 配置 .babelrc
{
  "presets": [
    ["latest", {
      "es2015": {
        "modules": false
      }
    }]
  ],
  "plugins": ["external-helpers"]
}
4. 配置  rollup.config.js
import babel from 'rollup-plugin-babel';
import resolve from 'rollup-plugin-node-resolve';

export default {
  input: 'src/index.js',
  output: {
    file: 'build/bundle.js',
    format: 'cjs'
  },
  plugins: [
    resolve(),
    babel({
        exclude: 'node_modules/**'
    })
  ]
};
  • 使用 rollup
1. 將 webpack 環(huán)境的 JS 代碼拷貝過來
2. 修改 package.json 的 scripts
  "scripts": {
    "start": "rollup -c rollup.config.js"
  }
3. 運(yùn)行 npm start
  • 關(guān)于工具
rollup 功能單一,webpack 功能強(qiáng)大
參考設(shè)計(jì)原則和《Linux/Unix設(shè)計(jì)思想》
工具要盡量功能單一协怒,可集成涝焙,可擴(kuò)展
wangEditor 用的 gulp + rollup

3. 關(guān)于 JS 眾多模塊化標(biāo)準(zhǔn)

  • 沒有模塊化
  • AMD 成為標(biāo)準(zhǔn),require.js (也有 CMD)
  • 前端打包工具孕暇,是的 nodejs 模塊化可以被使用
  • ES6 出現(xiàn)仑撞,想統(tǒng)一現(xiàn)在所有模塊化標(biāo)準(zhǔn)
  • nodejs 積極支持,瀏覽器尚未統(tǒng)一
  • 你可以自造 lib 妖滔,但是不要自造標(biāo)準(zhǔn)K硐!座舍!

【解答】

  • 語法: import export (注意有無 default)
  • 環(huán)境: babel 編譯 ES6 語法沮翔,模塊化可用 webpack 和 rollup
  • 擴(kuò)展: 說一下自己對模塊化標(biāo)準(zhǔn)統(tǒng)一的期待

2-9 class

【題目】

Class 與 JS 構(gòu)造函數(shù)的區(qū)別?

  • Class 在語法上更加貼合面向?qū)ο蟮膶懛?/li>
  • Class 實(shí)現(xiàn)繼承更加易讀曲秉、易理解
  • 更易于寫 java 等后端語言的使用
  • 本質(zhì)還是語法糖采蚀,使用 prototype

【知識(shí)點(diǎn)】

JS 構(gòu)造函數(shù)

function MathHandle(x, y) {
  this.x = x;
  this.y = y;
}

MathHandle.prototype.add = function () {
  return this.x + this.y;
};

var m = new MathHandle(1, 2);
console.log(m.add());

// typeof MathHandle // "function"
// MathHandle === MathHandle.prototype.constructor // true
// m.__proto__ === MathHandle.prototype // true

Class 基本語法

class MathHandle {
  constructor (x, y) {
    this.x = x;
    this.y = y;
  }

  add() {
    return this.x + this.y;
  }
}
const m = new MathHandle(1, 2);
console.log(m.add());
// typeof MathHandle // "function"
// MathHandle === MathHandle.prototype.constructor // true
// m.__proto__ === MathHandle.prototype // true

語法糖

class MathHandle {
  // ...
}

typeof MathHandle // "function"
MathHandle === MathHandle.prototype.constructor // true

繼承

  • 繼承 - JS
ES6 之前的繼承,是把低級構(gòu)造函數(shù)的原型岸浑,賦值成高級構(gòu)造函數(shù)的實(shí)例這種方式來實(shí)現(xiàn)的
// 動(dòng)物
function Animal() {
  this.eat = function () {
    console.log('animal eat');
  }
}
// 狗
function Dog() {
  this.bark = function () {
    console.log('dog bark');
  }
}
// 綁定原型搏存,實(shí)現(xiàn)繼承
Dog.prototype = new Animal();
// 哈士奇
var hashiqi = new Dog();
hashiqi.eat(); // animal eat
hashiqi.bark(); // dog bark
  • 繼承 - Class
// 動(dòng)物
class Animal {
  constructor(name) {
    this.name = name;
  }
  eat() {
    console.log(`${this.name} eat`);
  }
}
// 狗
class Dog extends Animal {
  constructor(name) {
    super(name);
    this.name = name;
  }
  say() {
     console.log(`${this.name} say`);
  }
}
// 哈士奇
const dog = new Dog('哈士奇');
dog.say(); // 哈士奇 say
dog.eat(); // 哈士奇 eat

【解答】

class Ad extends Component {
    constructor(props) {
        super(props);
        this.state = {
            data: []
        }
    }
    render() {
        return (
            <div>Hello, World!</div>
        )
    }
    componentDidMount() {

    }
}

2-13 Promise

【題目】

Promise 的用法?

【知識(shí)點(diǎn)】

Promise 的基本使用

  • Callback Hell
function loadImg(src, callback, fail) {
  var img = document.createElement('img');
  img.onload = function () {
    callback(img);
  }
  img.onerror = function () {
    fail();
  }
  img.src = src;
}

var src = 'https://www.imooc.com/courseimg/s/cover042_s.jpg';
loadImg(src, function (img) {
  console.log(img.width);
}, function () {
  console.log('failed');
})
  • Promise 語法
function loadImg(src) {
  const promise = new Promise(function (resolve, reject) {
    var img = document.createElement('img');
    img.onload = function () {
      resolve(img);
    }
    img.onerror = function () {
      reject();
    }
    img.src = src;
  })
  return promise;
};

var src = 'https://www.imooc.com/courseimg/s/cover042_s.jpg';
var result = loadImg(src);

result.then(function (img) {
  console.log(img.width);
}, function () {
  console.log('failed');
});

result.then(function (img) {
  console.log(img.height);
});

【解答】

  • new Promise 實(shí)例矢洲,而且要 return
  • new Promise 時(shí)要傳入函數(shù)璧眠,函數(shù)有 resolve reject 兩個(gè)參數(shù)
  • 成功時(shí)執(zhí)行 resolve() 失敗時(shí)執(zhí)行 reject()
  • then 監(jiān)聽結(jié)果

2-16 總結(jié)一下 ES6 其他常用功能

題目

總結(jié)一下 ES6 其他常用功能?

  • let/const
  • 多行字符串/模板變量
  • 解構(gòu)賦值
  • 塊級作用域
  • 函數(shù)默認(rèn)參數(shù)
  • 箭頭函數(shù) (this)

知識(shí)點(diǎn)

  • let/const
// JS
var i = 10;
i = 100;

// ES6
let i = 10;
i = 100;  // 正確
const j = 20;
j = 200;  // 報(bào)錯(cuò)
  • 多行字符串/模板變量
// JS
var name = 'zhangsan', age = 20, html = '';
html += '<div>';
html += ' <p>' + name + '</p>';
html += ' <p>' + age + '</p>';
html += '</div>';

// ES6
const name = 'zhangsan', age = 20;
const html = `<div>
                     <p>${name}</p>
                     <p>${age}</p>
             </div>`;
console.log(html);
  • 解構(gòu)賦值
// JS
var obj = { a: 100, b: 200 };
var a = obj.a;
var b = obj.b;

var arr = ['xxx', 'yyy', 'zzz'];
var x = arr[0];
// ES6
const obj = { a: 10, b: 20, c: 30 };
const { a, c } = obj;
console.log(a);
console.log(c);

const arr = ['xxx', 'yyy', 'zzz'];
const [x, y, z] = arr;
console.log(x);
console.log(y);
console.log(z);
  • 塊級作用域
// JS
var obj = { a: 100, b: 200 };
for (var item in obj) {
  console.log(item);
}
console.log(item); // 'b'

// ES6
const obj = { a: 100, b: 200 };
for (let item in obj) {
  console.log(item);
}
console.log(item); // undefined
  • 函數(shù)默認(rèn)參數(shù)
// JS
function fn(a, b) {
  if (b == null) {
    b = 0;
  }
}

// ES6
function fn(a, b=0) {

}
  • 箭頭函數(shù)
// JS
var arr = [1, 2, 3];
arr.map(function (item) {
  return item + 1;
});

// ES6
const arr = [1, 2, 3];
arr.map(item => item + 1);
arr.map((item, index) => {
  console.log(index);
  return item + 1;
});
function fn() {
  console.log('real', this); // {a: 100}
  var arr = [1, 2, 3];
  // 普通 JS
  arr.map(function (item) {
    console.log('js', this); // window
    return item + 1;
  });
  // 箭頭函數(shù)
  arr.map(item => {
    console.log('es6', this); // {a: 100}
    return item + 1;
  });
}
fn.call({a: 100});

第3章 原型

3-1 開始

  • 《前端 JS 面試技巧》已經(jīng)講解過原型的基礎(chǔ)知識(shí)
  • 高級面試題读虏,光會(huì)原型基礎(chǔ)還不夠责静,還要實(shí)際應(yīng)用
  • zepto jquery 中如何用原型?
  • 順便也算是解讀了 zepto 和 jquery 的部分源碼

題目

原型如何實(shí)際應(yīng)用盖桥?

  • jquery 和 zepto 的簡單使用
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <p>jquery test 1</p>
    <p>jquery test 2</p>
    <p>jquery test 3</p>

    <div id="div1">
        <p>jquery test in div</p>
    </div>

    <script type="text/javascript" src="./jquery-3.2.1.js"></script>
    <script type="text/javascript">
        var $p = $('p');
        $p.css('color', 'red'); // css 是原型方法
        console.log($p.html()); // html 是原型方法
        
        var $div1 = $('#div1')
        $div1.css('color', 'blue'); // css 是原型方法
        console.log($div1.html()); // html 是原型方法
    </script>
</body>
</html>
  • zepto 如何使用原型
(function (window) {

  var zepto = {};

  function Z(dom, selector) {
      var i, len = dom ? dom.length : 0;
      for (i = 0; i < len; i++) {
          this[i] = dom[i];
      }
      this.length = len;
      this.selector = selector || '';
  }

  zepto.Z = function (dom, selector) {
      return new Z(dom, selector);
  };

  zepto.init = function (selector) {
      var slice = Array.prototype.slice;
      var dom = slice.call(document.querySelectorAll(selector));
      return zepto.Z(dom, selector);
  };

  var $ = function (selector) {
      return zepto.init(selector);
  };
  window.$ = $

  $.fn = {
      css: function (key, value) {
          alert('css');
      },
      html: function (value) {
          return '這是一個(gè)模擬的 html 函數(shù)';
      }
  }
  Z.prototype = $.fn;
})(window);
  • jquery 如何使用原型
(function (window) {

    var jQuery = function (selector) {
        return new jQuery.fn.init(selector)
    };

    jQuery.fn = {
        css: function (key, value) {
            alert('css');
        },
        html: function (value) {
            return 'html';
        }
    };

    var init = jQuery.fn.init = function (selector) {
        var slice = Array.prototype.slice;
        var dom = slice.call(document.querySelectorAll(selector));

        var i, len = dom ? dom.length : 0;
        for (i = 0; i < len; i++) {
            this[i] = dom[i];
        }
        this.length = len;
        this.selector = selector || '';
    }

    init.prototype = jQuery.fn;

    window.$ = jQuery;

})(window);

原型如何滿足擴(kuò)展灾螃?

第4章 異步

  • 《前端 JS 面試技巧》講到異步的基礎(chǔ)
  • 高級面試會(huì)問到更多的內(nèi)容
  • 如 event-loop Promise Async/Await 等

題目

什么是單線程,和異步有什么關(guān)系揩徊?

  • 單線程 - 只有一個(gè)線程腰鬼,同一時(shí)間只能做一件事
// 循環(huán)運(yùn)行期間,JS 執(zhí)行和 DOM 渲染暫時(shí)卡頓
var i, sum = 0;
for (i = 0; i < 1000000000; i++) {
  sum += i;
}
console.log(sum);

// alert 不處理塑荒, JS 執(zhí)行和 DOM 渲染暫時(shí)卡頓
console.log(1);
alert('hello');
console.log(2);
  • 原因 - 避免 DOM 渲染的沖突
瀏覽器需要渲染 DOM
JS 可以修改 DOM 結(jié)構(gòu)
JS 執(zhí)行的時(shí)候熄赡,瀏覽器 DOM 渲染會(huì)暫停
兩段 JS 也不能同時(shí)執(zhí)行(都修改 DOM 就沖突了)
webworker 支持多線程,但是不能訪問 DOM
  • 解決方案 - 異步
    什么是 callback齿税?異步完成之后要執(zhí)行的函數(shù)
問題一:沒按照書寫方式執(zhí)行彼硫,可讀性查
問題二:callback 中不容易模塊化

什么是 event-loop?

  • 文字解釋
事件輪詢,JS 實(shí)現(xiàn)異步的具體解決方案
同步代碼拧篮,直接執(zhí)行
異步函數(shù)先放在 "異步隊(duì)列" 中
待同步函數(shù)執(zhí)行完畢词渤,輪詢執(zhí)行 "異步隊(duì)列" 的函數(shù)

如果只用 jquery 如何解決異步?- Deferred

  • 是否用過 jQuery 的 Deferred
jQuery 1.5 的變化
使用 jQuery Deferred
初步引入 Promise 概念
  • jQuery 1.5 的變化 - 1.5 之前
var ajax = $.ajax({
  url: 'data.json',
  success: function () {
    console.log('success1');
    console.log('success1');
    console.log('success1');
  },
  error: function () {
    console.log('error');
  }
})
console.log(ajax); // 返回一個(gè) XHR 對象
  • jQuery 1.5 的變化 - 1.5 之后
var ajax = $.ajax('data.json');
ajax.done(function () {
      console.log('success 1');
    })
    .fail(function () {
      console.log('error');
    })
    .done(function () {
      console.log('success 2');
    })
console.log(ajax); // 返回一個(gè) deferred 對象
// 很像 Promise 的寫法
var ajax = $.ajax('data.json');
ajax.then(function () {
        console.log('success 1');
      }, function () {
        console.log('error 1');
      })
      .then(function () {
        console.log('success 2');
      }, function () {
        console.log('error 2');
      })
  • jQuery 1.5 的變化
無法改變 JS 異步和單線程的本質(zhì)
只能從寫法上杜絕 callback 這種形式
它是一種語法糖形式串绩,但是解耦了代碼
很好的體現(xiàn):開放封閉原則 ( 對擴(kuò)展開發(fā)缺虐,對修改封閉 )
  • 使用 jQuery Deferred
var wait = function () {
  var task = function () {
     console.log('執(zhí)行完成');
     console.log('此處新需求......');
     console.log('第一步');
     console.log('第二步');
     console.log('第三步');
  };
  setTimeout(task, 2000);
};
wait();
function waitHandle() {
   var dtd = $.Deferred();
   var wait = function (dtd) {
       var task = function () {
           console.log('執(zhí)行完成');
           dtd.resolve();
           // dtd.reject()
       }
       setTimeout(task, 2000);
       return dtd.promise(); // return dtd; => return dtd.promise();
   }
   return wait(dtd);
}

var w = waitHandle();
// w.then(function () {  
// => 1.w 接收到的不再是一個(gè) dtd 對象,而是一個(gè) promise 對象
// => 2.只有 .then .done .fail 這種被動(dòng)監(jiān)聽方法
// => 3.不再支持 .resolve .reject 這種主動(dòng)方法的調(diào)用
$.when(w).then(function () {
    console.log('ok 1');
}, function () {
    console.log('err 1');
});
  • jQuery 里引入 promise
總結(jié)赏参,dtd 的 API 可分成兩類志笼,用意不同
第一類: dtd.resolve  dtd.reject
第二類: dtd.then  dtd.done  dtd.fail
這兩類應(yīng)該分開,否則后果很嚴(yán)重把篓!
可以在上面代碼最后執(zhí)行 dtd.reject() 試一下后果

Promise 的基本使用和原理纫溃?

  • 基本語法回顧
function loadImg(src) {
  const promise = new Promise(function (resolve, reject) {
    var img = document.createElement('img');
    img.onload = function () {
      resolve(img);
    }
    img.onerror = function () {
      reject();
    }
    img.src = src;
  })
  return promise;
};

var src = 'https://www.imooc.com/courseimg/s/cover042_s.jpg';
var result = loadImg(src);

result.then(function (img) {
  console.log(img.width);
}, function () {
  console.log('failed');
});

result.then(function (img) {
  console.log(img.height);
});
  • 異常捕獲
// 捕獲程序錯(cuò)誤異常
// throw new Error('自定義錯(cuò)誤');

result.then(function (img) {
  console.log(img.width);
  return img;
}).then(function (img) {
  console.log(img.height);
}).catch(function (ex) {
  // 統(tǒng)一捕獲異常
  console.log(ex);
})
// 捕獲業(yè)務(wù)邏輯異常
// reject('圖片加載失敗');
// var src = 'https://cover042_sXXX.jpg';

result.then(function (img) {
  console.log(img.width);
  return img;
}).then(function (img) {
  console.log(img.height);
}).catch(function (ex) {
  // 統(tǒng)一捕獲異常
  console.log(ex);
})
  • 多個(gè)串聯(lián)
//業(yè)務(wù)需求;先加載一個(gè)韧掩,再加載另外一個(gè)
var src1 = 'https://www.imooc.com/courseimg/s/cover042_s.jpg';
var result1 = loadImg(src1);
var src2 = 'https://coding.imooc.com/static/module/class/content/img/190/section5-img.png';
var result2 = loadImg(src2);

// 鏈?zhǔn)讲僮?result1.then(function (img) {
  console.log('第一個(gè)圖片加載完成', img.width); // 240
  return result2;
}).then(function (img) {
  console.log('第二個(gè)圖片加載完成', img.width); // 998
}).catch(function (ex) {
  // 統(tǒng)一捕獲異常
  console.log(ex);
})
  • Promise.all 和 Promise.race
// 全部完成才執(zhí)行
Promise.all([result1, result2]).then(function (datas)  {
 console.log(datas[0]);
 console.log(datas[1]);
});
// 只要有一個(gè)完成就執(zhí)行
Promise.race([result1, result2]).then(function (data)  {
 console.log(data);
});
  • Promise 標(biāo)準(zhǔn)
// 關(guān)于“標(biāo)準(zhǔn)”的閑談
任何技術(shù)推廣使用都需要一套標(biāo)準(zhǔn)來支撐
如 html js css http 等紊浩,無規(guī)矩不成方圓
任何不符合標(biāo)準(zhǔn)的東西,終將會(huì)被用戶拋棄
不要挑戰(zhàn)標(biāo)準(zhǔn)疗锐,不要自造標(biāo)準(zhǔn)
// Promise 標(biāo)準(zhǔn) - 狀態(tài)變化
三種狀態(tài):pending fulfilled rejected
初始狀態(tài)是 pending
pending 變?yōu)?fulfilled 坊谁,或者 pending 變?yōu)?rejected
狀態(tài)變化不可逆
// Promise 標(biāo)準(zhǔn) - then
Promise 實(shí)例必須實(shí)現(xiàn) then 這個(gè)方法
then() 必須可以接收兩個(gè)函數(shù)作為參數(shù)
then() 返回的必須是一個(gè) Promise 實(shí)例

介紹一下 async/await(和 Promise 的區(qū)別、聯(lián)系)滑臊?

  • then 只是將 callback 拆分了
var w = waitHandle();
w.then(function () { 
    console.log('ok 1');
}, function () {
    console.log('err 1');
}).then(function () { 
    console.log('ok 2');
}, function () {
    console.log('err 2');
});
  • async/await 是最直接的同步寫法
const load = async function () {
  const result1 = await loadImg(src1);
  console.log(result1);
  const result2 = await loadImg(src2);
  console.log(result2);  
}
load();
  • 語法
使用 await 口芍,函數(shù)必須用 async 標(biāo)識(shí)
await 后面跟的是一個(gè) Promise 實(shí)例
需要 babel-polyfill
  • 坑來了
// webpack 打包
1.首先,npm i babel-polyfill -D
2.運(yùn)行報(bào)錯(cuò)雇卷,Uncaught ReferenceError: regeneratorRuntime is not defined
3.在 .babelrc 文件中添加:
    "plugins": [
        [
            "transform-runtime",
            {
                "helpers": false,
                "polyfill": false,
                "regenerator": true,
                "moduleName": "babel-runtime"
            }
        ]
    ]
4.運(yùn)行報(bào)錯(cuò)鬓椭,ReferenceError: Unknown plugin "transform-runtime" specified
5.npm install babel-plugin-transform-runtime -D
6.運(yùn)行再次報(bào)錯(cuò),Cannot use import statement outside a module
7.<script type="module"></script>
8.成功
// rollup 打包
1.npm i babel-polyfill -D
之前也報(bào)和 webpack 相同的錯(cuò)誤关划,自己就好了小染,原因未知
  • 小結(jié)
promise 是對異步回調(diào)的封裝
async await 是使用 promise 時(shí)的一種擴(kuò)展
完全是同步的寫法,再也沒有回調(diào)函數(shù)
但是:改變不了 JS 單線程贮折、異步的本質(zhì)

目前 JS 解決異步的方案有哪些裤翩?

  • jQuery Deferred
  • Promise
  • Async/Await
  • Generator
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市调榄,隨后出現(xiàn)的幾起案子踊赠,更是在濱河造成了極大的恐慌,老刑警劉巖每庆,帶你破解...
    沈念sama閱讀 216,324評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件臼疫,死亡現(xiàn)場離奇詭異,居然都是意外死亡扣孟,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評論 3 392
  • 文/潘曉璐 我一進(jìn)店門荣赶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來凤价,“玉大人鸽斟,你說我怎么就攤上這事±担” “怎么了富蓄?”我有些...
    開封第一講書人閱讀 162,328評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長慢逾。 經(jīng)常有香客問我立倍,道長,這世上最難降的妖魔是什么侣滩? 我笑而不...
    開封第一講書人閱讀 58,147評論 1 292
  • 正文 為了忘掉前任口注,我火速辦了婚禮,結(jié)果婚禮上君珠,老公的妹妹穿的比我還像新娘寝志。我一直安慰自己,他們只是感情好策添,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,160評論 6 388
  • 文/花漫 我一把揭開白布材部。 她就那樣靜靜地躺著,像睡著了一般唯竹。 火紅的嫁衣襯著肌膚如雪乐导。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,115評論 1 296
  • 那天浸颓,我揣著相機(jī)與錄音物臂,去河邊找鬼。 笑死猾愿,一個(gè)胖子當(dāng)著我的面吹牛鹦聪,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蒂秘,決...
    沈念sama閱讀 40,025評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼泽本,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了姻僧?” 一聲冷哼從身側(cè)響起规丽,我...
    開封第一講書人閱讀 38,867評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎撇贺,沒想到半個(gè)月后当娱,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體店雅,經(jīng)...
    沈念sama閱讀 45,307評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,528評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了媒楼。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片晚顷。...
    茶點(diǎn)故事閱讀 39,688評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出遵倦,到底是詐尸還是另有隱情,我是刑警寧澤官撼,帶...
    沈念sama閱讀 35,409評論 5 343
  • 正文 年R本政府宣布梧躺,位于F島的核電站,受9級特大地震影響傲绣,放射性物質(zhì)發(fā)生泄漏掠哥。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,001評論 3 325
  • 文/蒙蒙 一秃诵、第九天 我趴在偏房一處隱蔽的房頂上張望续搀。 院中可真熱鬧,春花似錦顷链、人聲如沸目代。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽榛了。三九已至,卻和暖如春煞抬,著一層夾襖步出監(jiān)牢的瞬間霜大,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評論 1 268
  • 我被黑心中介騙來泰國打工革答, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留战坤,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,685評論 2 368
  • 正文 我出身青樓残拐,卻偏偏與公主長得像途茫,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子溪食,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,573評論 2 353

推薦閱讀更多精彩內(nèi)容

  • 前端開發(fā)面試題 面試題目: 根據(jù)你的等級和職位的變化囊卜,入門級到專家級,廣度和深度都會(huì)有所增加错沃。 題目類型: 理論知...
    怡寶丶閱讀 2,580評論 0 7
  • 《家庭公約》“日念一好”打卡第137天(張利平2019.11.13) 日念家人一好處栅组,念力加持享幸福! 正念枢析、正行...
  • 從惠州回來玉掸,到過年從過年的年例,到坐車上來廣州醒叁,再到從我哥家到學(xué)校司浪,再到和你單獨(dú)在一起泊业,這個(gè)過程里面,你我比以前更...
    減肥的女孩閱讀 195評論 0 0
  • 小時(shí)候過年 大人給小孩買新衣服 是期待的幸福 現(xiàn)在過年 還是大人給小孩買新衣服 只不過 以前的小孩長成了大人 曾經(jīng)...
    19號船長閱讀 213評論 0 0