字節(jié)前端必會面試題

常見的水平垂直方式有幾種?

//利用絕對定位具练,先將元素的左上角通過 top:50%和 left:50%定位到頁面的中心乍构,然后再通過 translate 來調(diào)整元素的中心點(diǎn)到頁面的中心。該方法需要考慮瀏覽器兼容問題扛点。
.parent {
    position: relative;
}

.child {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%,-50%);
}
//利用絕對定位哥遮,設(shè)置四個(gè)方向的值都為 0,并將 margin 設(shè)置為 auto陵究,由于寬高固定眠饮,因此對應(yīng)方向?qū)崿F(xiàn)平分,可以實(shí)現(xiàn)水平和垂直方向上的居中铜邮。該方法適用于盒子有寬高的情況:
.parent {
    position: relative;
}

.child {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    margin: auto;
}
//利用絕對定位仪召,先將元素的左上角通過 top:50%和 left:50%定位到頁面的中心,然后再通過 margin 負(fù)值來調(diào)整元素的中心點(diǎn)到頁面的中心牲距。該方法適用于盒子寬高已知的情況
.parent {
    position: relative;
}

.child {
    position: absolute;
    top: 50%;
    left: 50%;
    margin-top: -50px;     /* 自身 height 的一半 */
    margin-left: -50px;    /* 自身 width 的一半 */
}
//使用 flex 布局返咱,通過 align-items:center 和 justify-content:center 設(shè)置容器的垂直和水平方向上為居中對齊钥庇,然后它的子元素也可以實(shí)現(xiàn)垂直和水平的居中牍鞠。該方法要**考慮兼容的問題**,該方法在移動(dòng)端用的較多:
.parent {
    display: flex;
    justify-content:center;
    align-items:center;
}
//另外评姨,如果父元素設(shè)置了flex布局难述,只需要給子元素加上`margin:auto;`就可以實(shí)現(xiàn)垂直居中布局
.parent{
    display:flex;
}
.child{
    margin: auto;
}

----問題知識點(diǎn)分割線----

代碼輸出結(jié)果

const promise = new Promise((resolve, reject) => {
  console.log(1);
  setTimeout(() => {
    console.log("timerStart");
    resolve("success");
    console.log("timerEnd");
  }, 0);
  console.log(2);
});
promise.then((res) => {
  console.log(res);
});
console.log(4);

輸出結(jié)果如下:

1
2
4
timerStart
timerEnd
success

代碼執(zhí)行過程如下:

  • 首先遇到Promise構(gòu)造函數(shù),會先執(zhí)行里面的內(nèi)容吐句,打印1胁后;
  • 遇到定時(shí)器steTimeout,它是一個(gè)宏任務(wù)嗦枢,放入宏任務(wù)隊(duì)列攀芯;
  • 繼續(xù)向下執(zhí)行,打印出2文虏;
  • 由于Promise的狀態(tài)此時(shí)還是pending侣诺,所以promise.then先不執(zhí)行;
  • 繼續(xù)執(zhí)行下面的同步任務(wù)氧秘,打印出4年鸳;
  • 此時(shí)微任務(wù)隊(duì)列沒有任務(wù),繼續(xù)執(zhí)行下一輪宏任務(wù)丸相,執(zhí)行steTimeout搔确;
  • 首先執(zhí)行timerStart,然后遇到了resolve,將promise的狀態(tài)改為resolved且保存結(jié)果并將之前的promise.then推入微任務(wù)隊(duì)列膳算,再執(zhí)行timerEnd座硕;
  • 執(zhí)行完這個(gè)宏任務(wù),就去執(zhí)行微任務(wù)promise.then畦幢,打印出resolve的結(jié)果坎吻。

----問題知識點(diǎn)分割線----

函數(shù)柯里化

柯里化(currying) 指的是將一個(gè)多參數(shù)的函數(shù)拆分成一系列函數(shù),每個(gè)拆分后的函數(shù)都只接受一個(gè)參數(shù)宇葱。

對于已經(jīng)柯里化后的函數(shù)來說瘦真,當(dāng)接收的參數(shù)數(shù)量與原函數(shù)的形參數(shù)量相同時(shí),執(zhí)行原函數(shù)黍瞧; 當(dāng)接收的參數(shù)數(shù)量小于原函數(shù)的形參數(shù)量時(shí)诸尽,返回一個(gè)函數(shù)用于接收剩余的參數(shù),直至接收的參數(shù)數(shù)量與形參數(shù)量一致印颤,執(zhí)行原函數(shù)您机。

----問題知識點(diǎn)分割線----

對瀏覽器的緩存機(jī)制的理解

瀏覽器緩存的全過程:

  • 瀏覽器第一次加載資源,服務(wù)器返回 200年局,瀏覽器從服務(wù)器下載資源文件际看,并緩存資源文件與 response header,以供下次加載時(shí)對比使用矢否;

  • 下一次加載資源時(shí)仲闽,由于強(qiáng)制緩存優(yōu)先級較高,先比較當(dāng)前時(shí)間與上一次返回 200 時(shí)的時(shí)間差僵朗,如果沒有超過 cache-control 設(shè)置的 max-age赖欣,則沒有過期,并命中強(qiáng)緩存验庙,直接從本地讀取資源顶吮。如果瀏覽器不支持HTTP1.1,則使用 expires 頭判斷是否過期粪薛;

  • 如果資源已過期悴了,則表明強(qiáng)制緩存沒有被命中,則開始協(xié)商緩存违寿,向服務(wù)器發(fā)送帶有 If-None-Match 和 If-Modified-Since 的請求湃交;

  • 服務(wù)器收到請求后,優(yōu)先根據(jù) Etag 的值判斷被請求的文件有沒有做修改陨界,Etag 值一致則沒有修改巡揍,命中協(xié)商緩存,返回 304菌瘪;如果不一致則有改動(dòng)腮敌,直接返回新的資源文件帶上新的 Etag 值并返回 200阱当;

  • 如果服務(wù)器收到的請求沒有 Etag 值,則將 If-Modified-Since 和被請求文件的最后修改時(shí)間做比對糜工,一致則命中協(xié)商緩存弊添,返回 304;不一致則返回新的 last-modified 和文件并返回 200捌木;

    很多網(wǎng)站的資源后面都加了版本號油坝,這樣做的目的是:每次升級了 JS 或 CSS 文件后,為了防止瀏覽器進(jìn)行緩存刨裆,強(qiáng)制改變版本號澈圈,客戶端瀏覽器就會重新下載新的 JS 或 CSS 文件 ,以保證用戶能夠及時(shí)獲得網(wǎng)站的最新更新帆啃。

----問題知識點(diǎn)分割線----

如何避免ajax數(shù)據(jù)請求重新獲取

一般而言瞬女,ajax請求的數(shù)據(jù)都放在redux中存取。

----問題知識點(diǎn)分割線----

Promise.resolve

Promise.resolve = function(value) {
    // 1.如果 value 參數(shù)是一個(gè) Promise 對象努潘,則原封不動(dòng)返回該對象
    if(value instanceof Promise) return value;
    // 2.如果 value 參數(shù)是一個(gè)具有 then 方法的對象诽偷,則將這個(gè)對象轉(zhuǎn)為 Promise 對象,并立即執(zhí)行它的then方法
    if(typeof value === "object" && 'then' in value) {
        return new Promise((resolve, reject) => {
           value.then(resolve, reject);
        });
    }
    // 3.否則返回一個(gè)新的 Promise 對象疯坤,狀態(tài)為 fulfilled
    return new Promise(resolve => resolve(value));
}

----問題知識點(diǎn)分割線----

數(shù)組去重

使用 indexOf/includes 實(shí)現(xiàn)

function unique(arr) {
    var res = [];
    for(var i = 0; i < arr.length; i++) {
        if(res.indexOf(arr[i]) === -1) res.push(arr[i]);
        // if(!res.includes(arr[i])) res.push(arr[i]);
    }
    return res;
}

使用 filter(forEach) + indexOf/includes 實(shí)現(xiàn)

// filter
function unique(arr) {
    var res = arr.filter((value, index) => {
        // 只存第一個(gè)出現(xiàn)的元素
        return arr.indexOf(value) === index;
    });
    return res;
}
// forEach
function unique(arr) {
    var res = [];
    arr.forEach((value) => {
        if(!res.includes(value)) res.push(value);
    });
    return res;
}

非 API 版本(原生)實(shí)現(xiàn)

function unique(arr) {
    var res = [];
    for(var i = 0; i < arr.length; i++) {
        var flag = false;
        for(var j = 0; j < res.length; j++) {
            if(arr[i] === res[j]) {
                flag = true;
                break;
            }
        }
        if(flag === false) res.push(arr[i]);
    }
    return res;
}

ES6 使用 Set + 擴(kuò)展運(yùn)算符(...)/Array.from() 實(shí)現(xiàn)

function unique(arr) {
    // return [...new Set(arr)];
    return Array.from(new Set(arr));
}

----問題知識點(diǎn)分割線----

documentFragment 是什么报慕?用它跟直接操作 DOM 的區(qū)別是什么?

MDN中對documentFragment的解釋:

DocumentFragment压怠,文檔片段接口眠冈,一個(gè)沒有父對象的最小文檔對象。它被作為一個(gè)輕量版的 Document使用刑峡,就像標(biāo)準(zhǔn)的document一樣洋闽,存儲由節(jié)點(diǎn)(nodes)組成的文檔結(jié)構(gòu)玄柠。與document相比突梦,最大的區(qū)別是DocumentFragment不是真實(shí) DOM 樹的一部分,它的變化不會觸發(fā) DOM 樹的重新渲染羽利,且不會導(dǎo)致性能等問題宫患。

當(dāng)我們把一個(gè) DocumentFragment 節(jié)點(diǎn)插入文檔樹時(shí),插入的不是 DocumentFragment 自身这弧,而是它的所有子孫節(jié)點(diǎn)娃闲。在頻繁的DOM操作時(shí),我們就可以將DOM元素插入DocumentFragment匾浪,之后一次性的將所有的子孫節(jié)點(diǎn)插入文檔中皇帮。和直接操作DOM相比,將DocumentFragment 節(jié)點(diǎn)插入DOM樹時(shí)蛋辈,不會觸發(fā)頁面的重繪属拾,這樣就大大提高了頁面的性能将谊。

----問題知識點(diǎn)分割線----

寫版本號排序的方法

題目描述:有一組版本號如下['0.1.1', '2.3.3', '0.302.1', '4.2', '4.3.5', '4.3.4.5']。現(xiàn)在需要對其進(jìn)行排序渐白,排序的結(jié)果為 ['4.3.5','4.3.4.5','2.3.3','0.302.1','0.1.1']

實(shí)現(xiàn)代碼如下:

arr.sort((a, b) => {
  let i = 0;
  const arr1 = a.split(".");
  const arr2 = b.split(".");

  while (true) {
    const s1 = arr1[i];
    const s2 = arr2[i];
    i++;
    if (s1 === undefined || s2 === undefined) {
      return arr2.length - arr1.length;
    }

    if (s1 === s2) continue;

    return s2 - s1;
  }
});
console.log(arr);

----問題知識點(diǎn)分割線----

談一談隊(duì)頭阻塞問題

什么是隊(duì)頭阻塞尊浓?

對于每一個(gè)HTTP請求而言,這些任務(wù)是會被放入一個(gè)任務(wù)隊(duì)列中串行執(zhí)行的纯衍,一旦隊(duì)首任務(wù)請求太慢時(shí)栋齿,就會阻塞后面的請求處理,這就是HTTP隊(duì)頭阻塞問題襟诸。

有什么解決辦法嗎??

并發(fā)連接

我們知道對于一個(gè)域名而言瓦堵,是允許分配多個(gè)長連接的,那么可以理解成增加了任務(wù)隊(duì)列歌亲,也就是說不會導(dǎo)致一個(gè)任務(wù)阻塞了該任務(wù)隊(duì)列的其他任務(wù)谷丸,在RFC規(guī)范中規(guī)定客戶端最多并發(fā)2個(gè)連接,不過實(shí)際情況就是要比這個(gè)還要多应结,舉個(gè)例子刨疼,Chrome中是6個(gè)。

域名分片

  • 顧名思義鹅龄,我們可以在一個(gè)域名下分出多個(gè)二級域名出來揩慕,而它們最終指向的還是同一個(gè)服務(wù)器,這樣子的話就可以并發(fā)處理的任務(wù)隊(duì)列更多扮休,也更好的解決了隊(duì)頭阻塞的問題迎卤。
  • 舉個(gè)例子,比如TianTian.com玷坠,可以分出很多二級域名蜗搔,比如Day1.TianTian.comDay2.TianTian.com,Day3.TianTian.com,這樣子就可以有效解決隊(duì)頭阻塞問題八堡。

----問題知識點(diǎn)分割線----

對原型樟凄、原型鏈的理解

在JavaScript中是使用構(gòu)造函數(shù)來新建一個(gè)對象的酸些,每一個(gè)構(gòu)造函數(shù)的內(nèi)部都有一個(gè) prototype 屬性迈倍,它的屬性值是一個(gè)對象,這個(gè)對象包含了可以由該構(gòu)造函數(shù)的所有實(shí)例共享的屬性和方法胶坠。當(dāng)使用構(gòu)造函數(shù)新建一個(gè)對象后挂谍,在這個(gè)對象的內(nèi)部將包含一個(gè)指針叔壤,這個(gè)指針指向構(gòu)造函數(shù)的 prototype 屬性對應(yīng)的值,在 ES5 中這個(gè)指針被稱為對象的原型口叙。一般來說不應(yīng)該能夠獲取到這個(gè)值的炼绘,但是現(xiàn)在瀏覽器中都實(shí)現(xiàn)了 proto 屬性來訪問這個(gè)屬性,但是最好不要使用這個(gè)屬性妄田,因?yàn)樗皇且?guī)范中規(guī)定的俺亮。ES5 中新增了一個(gè) Object.getPrototypeOf() 方法仗哨,可以通過這個(gè)方法來獲取對象的原型。

當(dāng)訪問一個(gè)對象的屬性時(shí)铅辞,如果這個(gè)對象內(nèi)部不存在這個(gè)屬性厌漂,那么它就會去它的原型對象里找這個(gè)屬性,這個(gè)原型對象又會有自己的原型斟珊,于是就這樣一直找下去苇倡,也就是原型鏈的概念。原型鏈的盡頭一般來說都是 Object.prototype 所以這就是新建的對象為什么能夠使用 toString() 等方法的原因囤踩。

特點(diǎn): JavaScript 對象是通過引用來傳遞的旨椒,創(chuàng)建的每個(gè)新對象實(shí)體中并沒有一份屬于自己的原型副本。當(dāng)修改原型時(shí)堵漱,與之相關(guān)的對象也會繼承這一改變综慎。

----問題知識點(diǎn)分割線----

函數(shù)柯里化

什么叫函數(shù)柯里化?其實(shí)就是將使用多個(gè)參數(shù)的函數(shù)轉(zhuǎn)換成一系列使用一個(gè)參數(shù)的函數(shù)的技術(shù)勤庐。還不懂示惊?來舉個(gè)例子。

function add(a, b, c) {
    return a + b + c
}
add(1, 2, 3)
let addCurry = curry(add)
addCurry(1)(2)(3)

現(xiàn)在就是要實(shí)現(xiàn) curry 這個(gè)函數(shù)愉镰,使函數(shù)從一次調(diào)用傳入多個(gè)參數(shù)變成多次調(diào)用每次傳一個(gè)參數(shù)米罚。

function curry(fn) {
    let judge = (...args) => {
        if (args.length == fn.length) return fn(...args)
        return (...arg) => judge(...args, ...arg)
    }
    return judge
}

----問題知識點(diǎn)分割線----

如何判斷數(shù)組類型

Array.isArray

----問題知識點(diǎn)分割線----

數(shù)組能夠調(diào)用的函數(shù)有那些?

  • push
  • pop
  • splice
  • slice
  • shift
  • unshift
  • sort
  • find
  • findIndex
  • map/filter/reduce 等函數(shù)式編程方法
  • 還有一些原型鏈上的方法:toString/valudOf

----問題知識點(diǎn)分割線----

單行丈探、多行文本溢出隱藏

  • 單行文本溢出
overflow: hidden;            // 溢出隱藏
text-overflow: ellipsis;      // 溢出用省略號顯示
white-space: nowrap;         // 規(guī)定段落中的文本不進(jìn)行換行

  • 多行文本溢出
overflow: hidden;            // 溢出隱藏
text-overflow: ellipsis;     // 溢出用省略號顯示
display:-webkit-box;         // 作為彈性伸縮盒子模型顯示录择。
-webkit-box-orient:vertical; // 設(shè)置伸縮盒子的子元素排列方式:從上到下垂直排列
-webkit-line-clamp:3;        // 顯示的行數(shù)

注意:由于上面的三個(gè)屬性都是 CSS3 的屬性,沒有瀏覽器可以兼容碗降,所以要在前面加一個(gè)-webkit- 來兼容一部分瀏覽器隘竭。

----問題知識點(diǎn)分割線----

介紹一下HTTPS和HTTP區(qū)別

HTTPS 要比 HTTPS 多了 secure 安全性這個(gè)概念,實(shí)際上讼渊, HTTPS 并不是一個(gè)新的應(yīng)用層協(xié)議动看,它其實(shí)就是 HTTP + TLS/SSL 協(xié)議組合而成,而安全性的保證正是 SSL/TLS 所做的工作精偿。

SSL

安全套接層(Secure Sockets Layer)

TLS

(傳輸層安全弧圆,Transport Layer Security)

現(xiàn)在主流的版本是 TLS/1.2, 之前的 TLS1.0赋兵、TLS1.1 都被認(rèn)為是不安全的笔咽,在不久的將來會被完全淘汰。

HTTPS 就是身披了一層 SSL 的 HTTP 霹期。

[圖片上傳失敗...(image-c15684-1662526631598)]

那么區(qū)別有哪些呢??

  • HTTP 是明文傳輸協(xié)議叶组,HTTPS 協(xié)議是由 SSL+HTTP 協(xié)議構(gòu)建的可進(jìn)行加密傳輸、身份認(rèn)證的網(wǎng)絡(luò)協(xié)議历造,比 HTTP 協(xié)議安全甩十。
  • HTTPS比HTTP更加安全船庇,對搜索引擎更友好,利于SEO,谷歌侣监、百度優(yōu)先索引HTTPS網(wǎng)頁鸭轮。
  • HTTPS標(biāo)準(zhǔn)端口443,HTTP標(biāo)準(zhǔn)端口80橄霉。
  • HTTPS需要用到SSL證書窃爷,而HTTP不用。

我覺得記住以下兩點(diǎn)HTTPS主要作用就行??

  1. 對數(shù)據(jù)進(jìn)行加密姓蜂,并建立一個(gè)信息安全通道按厘,來保證傳輸過程中的數(shù)據(jù)安全;
  2. 對網(wǎng)站服務(wù)器進(jìn)行真實(shí)身份認(rèn)證。

HTTPS的缺點(diǎn)

  • 證書費(fèi)用以及更新維護(hù)钱慢。
  • HTTPS 降低一定用戶訪問速度(實(shí)際上優(yōu)化好就不是缺點(diǎn)了)逮京。
  • HTTPS 消耗 CPU 資源,需要增加大量機(jī)器束莫。

----問題知識點(diǎn)分割線----

請實(shí)現(xiàn) DOM2JSON 一個(gè)函數(shù)懒棉,可以把一個(gè) DOM 節(jié)點(diǎn)輸出 JSON 的格式

題目描述:

<div>
  <span>
    <a></a>
  </span>
  <span>
    <a></a>
    <a></a>
  </span>
</div>

把上訴dom結(jié)構(gòu)轉(zhuǎn)成下面的JSON格式

{
  tag: 'DIV',
  children: [
    {
      tag: 'SPAN',
      children: [
        { tag: 'A', children: [] }
      ]
    },
    {
      tag: 'SPAN',
      children: [
        { tag: 'A', children: [] },
        { tag: 'A', children: [] }
      ]
    }
  ]
}

實(shí)現(xiàn)代碼如下:

function dom2Json(domtree) {
  let obj = {};
  obj.name = domtree.tagName;
  obj.children = [];
  domtree.childNodes.forEach((child) => obj.children.push(dom2Json(child)));
  return obj;
}

擴(kuò)展思考:如果給定的不是一個(gè) Dom 樹結(jié)構(gòu) 而是一段 html 字符串 該如何解析?

那么這個(gè)問題就類似 Vue 的模板編譯原理 我們可以利用正則 匹配 html 字符串 遇到開始標(biāo)簽 結(jié)束標(biāo)簽和文本 解析完畢之后生成對應(yīng)的 ast 并建立相應(yīng)的父子關(guān)聯(lián) 不斷的 advance 截取剩余的字符串 直到 html 全部解析完畢

----問題知識點(diǎn)分割線----

對執(zhí)行上下文的理解

1. 執(zhí)行上下文類型

(1)全局執(zhí)行上下文

任何不在函數(shù)內(nèi)部的都是全局執(zhí)行上下文,它首先會創(chuàng)建一個(gè)全局的window對象览绿,并且設(shè)置this的值等于這個(gè)全局對象漓藕,一個(gè)程序中只有一個(gè)全局執(zhí)行上下文。

(2)函數(shù)執(zhí)行上下文

當(dāng)一個(gè)函數(shù)被調(diào)用時(shí)挟裂,就會為該函數(shù)創(chuàng)建一個(gè)新的執(zhí)行上下文享钞,函數(shù)的上下文可以有任意多個(gè)。

(3)eval函數(shù)執(zhí)行上下文

執(zhí)行在eval函數(shù)中的代碼會有屬于他自己的執(zhí)行上下文诀蓉,不過eval函數(shù)不常使用栗竖,不做介紹。

2. 執(zhí)行上下文棧
  • JavaScript引擎使用執(zhí)行上下文棧來管理執(zhí)行上下文
  • 當(dāng)JavaScript執(zhí)行代碼時(shí)渠啤,首先遇到全局代碼狐肢,會創(chuàng)建一個(gè)全局執(zhí)行上下文并且壓入執(zhí)行棧中,每當(dāng)遇到一個(gè)函數(shù)調(diào)用沥曹,就會為該函數(shù)創(chuàng)建一個(gè)新的執(zhí)行上下文并壓入棧頂份名,引擎會執(zhí)行位于執(zhí)行上下文棧頂?shù)暮瘮?shù),當(dāng)函數(shù)執(zhí)行完成之后妓美,執(zhí)行上下文從棧中彈出僵腺,繼續(xù)執(zhí)行下一個(gè)上下文。當(dāng)所有的代碼都執(zhí)行完畢之后壶栋,從棧中彈出全局執(zhí)行上下文辰如。
let a = 'Hello World!';
function first() {
  console.log('Inside first function');
  second();
  console.log('Again inside first function');
}
function second() {
  console.log('Inside second function');
}
first();
//執(zhí)行順序
//先執(zhí)行second(),在執(zhí)行first()

3. 創(chuàng)建執(zhí)行上下文

創(chuàng)建執(zhí)行上下文有兩個(gè)階段:創(chuàng)建階段執(zhí)行階段

1)創(chuàng)建階段

(1)this綁定

  • 在全局執(zhí)行上下文中,this指向全局對象(window對象)
  • 在函數(shù)執(zhí)行上下文中贵试,this指向取決于函數(shù)如何調(diào)用琉兜。如果它被一個(gè)引用對象調(diào)用凯正,那么 this 會被設(shè)置成那個(gè)對象,否則 this 的值被設(shè)置為全局對象或者 undefined

(2)創(chuàng)建詞法環(huán)境組件

  • 詞法環(huán)境是一種有標(biāo)識符——變量映射的數(shù)據(jù)結(jié)構(gòu)豌蟋,標(biāo)識符是指變量/函數(shù)名廊散,變量是對實(shí)際對象或原始數(shù)據(jù)的引用。
  • 詞法環(huán)境的內(nèi)部有兩個(gè)組件:加粗樣式:環(huán)境記錄器:用來儲存變量個(gè)函數(shù)聲明的實(shí)際位置外部環(huán)境的引用:可以訪問父級作用域

(3)創(chuàng)建變量環(huán)境組件

  • 變量環(huán)境也是一個(gè)詞法環(huán)境梧疲,其環(huán)境記錄器持有變量聲明語句在執(zhí)行上下文中創(chuàng)建的綁定關(guān)系奸汇。

2)執(zhí)行階段 此階段會完成對變量的分配,最后執(zhí)行完代碼往声。

簡單來說執(zhí)行上下文就是指:

在執(zhí)行一點(diǎn)JS代碼之前擂找,需要先解析代碼。解析的時(shí)候會先創(chuàng)建一個(gè)全局執(zhí)行上下文環(huán)境浩销,先把代碼中即將執(zhí)行的變量贯涎、函數(shù)聲明都拿出來,變量先賦值為undefined慢洋,函數(shù)先聲明好可使用塘雳。這一步執(zhí)行完了,才開始正式的執(zhí)行程序普筹。

在一個(gè)函數(shù)執(zhí)行之前败明,也會創(chuàng)建一個(gè)函數(shù)執(zhí)行上下文環(huán)境,跟全局執(zhí)行上下文類似太防,不過函數(shù)執(zhí)行上下文會多出this妻顶、arguments和函數(shù)的參數(shù)。

  • 全局上下文:變量定義蜒车,函數(shù)聲明
  • 函數(shù)上下文:變量定義讳嘱,函數(shù)聲明,this酿愧,arguments

----問題知識點(diǎn)分割線----

對Promise的理解

Promise是異步編程的一種解決方案沥潭,它是一個(gè)對象,可以獲取異步操作的消息嬉挡,他的出現(xiàn)大大改善了異步編程的困境钝鸽,避免了地獄回調(diào),它比傳統(tǒng)的解決方案回調(diào)函數(shù)和事件更合理和更強(qiáng)大庞钢。

所謂Promise拔恰,簡單說就是一個(gè)容器,里面保存著某個(gè)未來才會結(jié)束的事件(通常是一個(gè)異步操作)的結(jié)果焊夸。從語法上說仁连,Promise 是一個(gè)對象,從它可以獲取異步操作的消息阱穗。Promise 提供統(tǒng)一的 API饭冬,各種異步操作都可以用同樣的方法進(jìn)行處理。

(1)Promise的實(shí)例有三個(gè)狀態(tài):

  • Pending(進(jìn)行中)
  • Resolved(已完成)
  • Rejected(已拒絕)

當(dāng)把一件事情交給promise時(shí)揪阶,它的狀態(tài)就是Pending昌抠,任務(wù)完成了狀態(tài)就變成了Resolved、沒有完成失敗了就變成了Rejected鲁僚。

(2)Promise的實(shí)例有兩個(gè)過程

  • pending -> fulfilled : Resolved(已完成)
  • pending -> rejected:Rejected(已拒絕)

注意:一旦從進(jìn)行狀態(tài)變成為其他狀態(tài)就永遠(yuǎn)不能更改狀態(tài)了炊苫。

Promise的特點(diǎn):

  • 對象的狀態(tài)不受外界影響。promise對象代表一個(gè)異步操作冰沙,有三種狀態(tài)侨艾,pending(進(jìn)行中)、fulfilled(已成功)拓挥、rejected(已失斶肜妗)。只有異步操作的結(jié)果侥啤,可以決定當(dāng)前是哪一種狀態(tài)当叭,任何其他操作都無法改變這個(gè)狀態(tài),這也是promise這個(gè)名字的由來——“承諾”盖灸;
  • 一旦狀態(tài)改變就不會再變蚁鳖,任何時(shí)候都可以得到這個(gè)結(jié)果。promise對象的狀態(tài)改變赁炎,只有兩種可能:從pending變?yōu)?code>fulfilled醉箕,從pending變?yōu)?code>rejected。這時(shí)就稱為resolved(已定型)徙垫。如果改變已經(jīng)發(fā)生了琅攘,你再對promise對象添加回調(diào)函數(shù),也會立即得到這個(gè)結(jié)果松邪。這與事件(event)完全不同坞琴,事件的特點(diǎn)是:如果你錯(cuò)過了它,再去監(jiān)聽是得不到結(jié)果的逗抑。

Promise的缺點(diǎn):

  • 無法取消Promise剧辐,一旦新建它就會立即執(zhí)行,無法中途取消邮府。
  • 如果不設(shè)置回調(diào)函數(shù)荧关,Promise內(nèi)部拋出的錯(cuò)誤,不會反應(yīng)到外部褂傀。
  • 當(dāng)處于pending狀態(tài)時(shí)忍啤,無法得知目前進(jìn)展到哪一個(gè)階段(剛剛開始還是即將完成)。

總結(jié): Promise 對象是異步編程的一種解決方案,最早由社區(qū)提出同波。Promise 是一個(gè)構(gòu)造函數(shù)鳄梅,接收一個(gè)函數(shù)作為參數(shù),返回一個(gè) Promise 實(shí)例未檩。一個(gè) Promise 實(shí)例有三種狀態(tài)戴尸,分別是pending、resolved 和 rejected冤狡,分別代表了進(jìn)行中孙蒙、已成功和已失敗。實(shí)例的狀態(tài)只能由 pending 轉(zhuǎn)變 resolved 或者rejected 狀態(tài)悲雳,并且狀態(tài)一經(jīng)改變挎峦,就凝固了,無法再被改變了合瓢。

狀態(tài)的改變是通過 resolve() 和 reject() 函數(shù)來實(shí)現(xiàn)的坦胶,可以在異步操作結(jié)束后調(diào)用這兩個(gè)函數(shù)改變 Promise 實(shí)例的狀態(tài),它的原型上定義了一個(gè) then 方法歪玲,使用這個(gè) then 方法可以為兩個(gè)狀態(tài)的改變注冊回調(diào)函數(shù)迁央。這個(gè)回調(diào)函數(shù)屬于微任務(wù),會在本輪事件循環(huán)的末尾執(zhí)行滥崩。

注意: 在構(gòu)造 Promise 的時(shí)候岖圈,構(gòu)造函數(shù)內(nèi)部的代碼是立即執(zhí)行的

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市钙皮,隨后出現(xiàn)的幾起案子蜂科,更是在濱河造成了極大的恐慌,老刑警劉巖短条,帶你破解...
    沈念sama閱讀 222,000評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件导匣,死亡現(xiàn)場離奇詭異,居然都是意外死亡茸时,警方通過查閱死者的電腦和手機(jī)贡定,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來可都,“玉大人缓待,你說我怎么就攤上這事∏” “怎么了旋炒?”我有些...
    開封第一講書人閱讀 168,561評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長签杈。 經(jīng)常有香客問我瘫镇,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,782評論 1 298
  • 正文 為了忘掉前任铣除,我火速辦了婚禮谚咬,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘通孽。我一直安慰自己序宦,他們只是感情好睁壁,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,798評論 6 397
  • 文/花漫 我一把揭開白布背苦。 她就那樣靜靜地躺著,像睡著了一般潘明。 火紅的嫁衣襯著肌膚如雪行剂。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,394評論 1 310
  • 那天钳降,我揣著相機(jī)與錄音厚宰,去河邊找鬼。 笑死遂填,一個(gè)胖子當(dāng)著我的面吹牛铲觉,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播吓坚,決...
    沈念sama閱讀 40,952評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼撵幽,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了礁击?” 一聲冷哼從身側(cè)響起盐杂,我...
    開封第一講書人閱讀 39,852評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎哆窿,沒想到半個(gè)月后链烈,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,409評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡挚躯,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,483評論 3 341
  • 正文 我和宋清朗相戀三年强衡,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片码荔。...
    茶點(diǎn)故事閱讀 40,615評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡漩勤,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出目胡,到底是詐尸還是另有隱情锯七,我是刑警寧澤,帶...
    沈念sama閱讀 36,303評論 5 350
  • 正文 年R本政府宣布誉己,位于F島的核電站眉尸,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜噪猾,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,979評論 3 334
  • 文/蒙蒙 一霉祸、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧袱蜡,春花似錦丝蹭、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,470評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至敏晤,卻和暖如春贱田,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背嘴脾。 一陣腳步聲響...
    開封第一講書人閱讀 33,571評論 1 272
  • 我被黑心中介騙來泰國打工男摧, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人译打。 一個(gè)月前我還...
    沈念sama閱讀 49,041評論 3 377
  • 正文 我出身青樓耗拓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親奏司。 傳聞我的和親對象是個(gè)殘疾皇子乔询,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,630評論 2 359

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

  • 以下題目是根據(jù)網(wǎng)上多份面經(jīng)收集而來的,題目相同意味著被問的頻率比較高(x3表示有三份面經(jīng)被問)结澄,有問題歡迎留言討論...
    Aniugel閱讀 2,402評論 0 7
  • UDP協(xié)議為什么不可靠哥谷? UDP在傳輸數(shù)據(jù)之前不需要先建立連接,遠(yuǎn)地主機(jī)的運(yùn)輸層在接收到UDP報(bào)文后麻献,不需要確認(rèn)们妥,...
    helloworld1024閱讀 112評論 0 0
  • 內(nèi)置類型 JS中分為七種內(nèi)置類型,其中內(nèi)置類型又分為兩大類型: 基本類型 對象(Object) 基本類型有六種: ...
    小白摘葡萄閱讀 697評論 0 2
  • 內(nèi)置類型 JS 中分為七種內(nèi)置類型勉吻,七種內(nèi)置類型又分為兩大類型:基本類型和對象(Object)监婶。 基本類型有六種:...
    C楚輝H閱讀 1,722評論 0 2
  • 一、xue的生命周期是什么 vue每個(gè)組件都是獨(dú)立的齿桃,惑惶,每個(gè)組件都有一個(gè)屬于他的生命周期,從一個(gè)組件創(chuàng)建短纵、數(shù)據(jù)初始...
    康娜閱讀 849評論 0 0