初級(jí)JavaScript 面試??紗?wèn)題

數(shù)據(jù)類(lèi)型

數(shù)據(jù)類(lèi)型

  • 基本類(lèi)型 Boolean,object, number, null, undefined, string, symbol (es6)

  • Symbol值通過(guò)Symbol( )生成,只要屬性名是屬于Symbol類(lèi)型的,就是獨(dú)一無(wú)二的,可以保證不會(huì)與其他屬性名產(chǎn)生沖突。

  • 引用類(lèi)型: 數(shù)組,函數(shù),對(duì)象

判斷變量的類(lèi)型

  • typeof 返回的是字符串,描述數(shù)據(jù)類(lèi)型。需要注意的是,對(duì)于null,object,function, array都返回object,并不會(huì)明確告訴是哪一種對(duì)象

  • instanceof及原理 ,判斷摸個(gè)對(duì)象是否是另一個(gè)對(duì)象的實(shí)例,返回布爾值

  • Object.prototype.toString.call() 判斷對(duì)象屬于哪種內(nèi)置類(lèi)型

深拷貝 淺拷貝

  • 淺拷貝拷貝的是內(nèi)存地址,兩者指向同一塊內(nèi)存空間,改變其中一個(gè)對(duì)象的值,另一個(gè)對(duì)象的值也會(huì)隨之變化。Object.assign() 方法用于將所有可枚舉的屬性的值從一個(gè)或多個(gè)源對(duì)象復(fù)制到目標(biāo)對(duì)象。它將返回目標(biāo)對(duì)象

  • 深拷貝是將一個(gè)對(duì)象從內(nèi)存中完整的拷貝出來(lái),并開(kāi)辟一個(gè)新的內(nèi)存空間儲(chǔ)存,修改器其中一個(gè)對(duì)象的值不會(huì)影響別的對(duì)象。JSON.parse(JSON.stringify()),對(duì)帶函數(shù)的對(duì)象只能用遞歸的方法實(shí)現(xiàn)

  • 手寫(xiě)深拷貝

    <pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="js" cid="n26" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: normal; background-color: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit; background-position: initial initial; background-repeat: initial initial;">function deepClone(source){
    const targetObj = source.constructor === Array ? [] : {}; // 判斷復(fù)制的目標(biāo)是數(shù)組還是對(duì)象
    for(let keys in source){ // 遍歷目標(biāo)
    if(source.hasOwnProperty(keys)){
    if(source[keys] && typeof source[keys] === 'object'){ // 如果值是對(duì)象,就遞歸一下
    targetObj[keys] = source[keys].constructor === Array ? [] : {};
    targetObj[keys] = deepClone(source[keys]);
    }else{ // 如果不是,就直接賦值
    targetObj[keys] = source[keys];
    }
    }
    }
    return targetObj;
    }</pre>

數(shù)據(jù)類(lèi)型轉(zhuǎn)換

  • 相等==和全等===

  • 強(qiáng)制轉(zhuǎn)換和隱式轉(zhuǎn)換

作用域

變量提升

  • js引擎會(huì)先對(duì)文件進(jìn)行預(yù)編譯,其中一部分工作邊便是將函數(shù)和變量的聲明提升到其對(duì)應(yīng)作用域的頂部。全局變量提升到全局作用域頂部,函數(shù)內(nèi)聲明的變量提升到函數(shù)作用域的頂部。其中變量會(huì)被先定義為undifined。es6中引用的塊作用域的概念。 let 和const不允許有這樣的操作,let 聲明以后不允許多次聲明同一名稱的變量,這樣避免了引起混亂。let只在let所在的代碼域內(nèi)有效,const聲明一個(gè)只讀的常量,一旦聲明常量的值無(wú)法改變

閉包

  • 閉包的形成:函數(shù)里面再定義一個(gè)函數(shù),內(nèi)部函數(shù)可以訪問(wèn)外部函數(shù)作用域的變量。如果外部函數(shù)不暴露這個(gè)內(nèi)部函數(shù)的話,外界就不知道這個(gè)內(nèi)部函數(shù)。這個(gè)內(nèi)部函數(shù)函數(shù)所能訪問(wèn)的變量的總和被稱為閉包。

  • 閉包的作用:閉包常常用來(lái)隱藏變量,給內(nèi)部函數(shù)的變量設(shè)置里只讀屬性,外部只能返回他的值,而不能修改他的值,從而起到了保護(hù)作用。但是閉包會(huì)造成某一塊內(nèi)存長(zhǎng)期被占用,消耗內(nèi)存

作用域鏈

全局作用域

  • 瀏覽器打開(kāi)一個(gè)頁(yè)面時(shí),會(huì)給js代碼提供一個(gè)全局的運(yùn)行環(huán)境,這個(gè)環(huán)境就是全局作用域。一個(gè)頁(yè)面只有一個(gè)全局作用域,這個(gè)全局作用域下有window對(duì)象,全局作用域下的變量和函數(shù)都會(huì)儲(chǔ)存在window下。

函數(shù)作用域

  • 函數(shù)作用域指聲明在函數(shù)內(nèi)部的變量,函數(shù)作用域包含在全局作用域下,全局作用域下可以有多個(gè)函數(shù)作用域

塊級(jí)作用域 var/let/const

  • 塊級(jí)作用域可通過(guò)let和const聲明,所聲明的變量在指定塊的作用域外無(wú)法被訪問(wèn),在一個(gè)函數(shù)內(nèi)部或一個(gè)代碼塊內(nèi)部被創(chuàng)建。const和let的作用域是一致的,不同的是const聲明一個(gè)只讀的常量,常量一旦聲明不允許改變 let的特點(diǎn):1. 變量提升不會(huì)提升到代碼塊的頂部,所以let一定要先聲明再使用,需要手動(dòng)放置到作用域頂部。2. var可以在同一個(gè)作用域內(nèi)重復(fù)聲明,let禁止在相同的作用域內(nèi)重復(fù)聲明。

作用域鏈?zhǔn)鞘裁?/strong>

  • 自由變量指當(dāng)前作用域中沒(méi)有定義的變量。 作用域鏈指由子作用域?qū)訉酉蚋缸饔糜蛑姓易杂米兞康年P(guān)系。

作用域和執(zhí)行上下文的區(qū)別

  • javascript屬于解釋性語(yǔ)言,js的執(zhí)行分為兩個(gè)階段:解釋階段和執(zhí)行階段。作用域在解釋階段,在函數(shù)定義時(shí)已經(jīng)確定,但是執(zhí)行上下文在函數(shù)執(zhí)行之前才被創(chuàng)建。 執(zhí)行上下文可能隨時(shí)會(huì)變,但時(shí)作用域在定義時(shí)就被確定,不會(huì)變。同一個(gè)作用域下,不同的調(diào)用會(huì)產(chǎn)生不同的執(zhí)行上下文。

原型

原型和原型鏈

舉例:描述構(gòu)造函數(shù)、實(shí)例和原型之間的關(guān)系

  • 原型指將所有對(duì)象的公共屬性儲(chǔ)存到一個(gè)對(duì)象中,然后讓每一個(gè)對(duì)象的protp記錄這個(gè)對(duì)象的地址,而這個(gè)公共屬性就是原型。

  • protp和constructor是對(duì)象的屬性,prototype是函數(shù)獨(dú)有的屬性。 proto 是一個(gè)對(duì)象指向另一個(gè)對(duì)象,指向它的原型對(duì)象。prototype是給其他對(duì)象提供共享屬性的對(duì)象,所有的對(duì)象都可以作用另一個(gè)對(duì)象的prototype來(lái)用。函數(shù)創(chuàng)建的對(duì)象.protp === 函數(shù).protptype。 constructor指向該對(duì)象的構(gòu)造函數(shù)。函數(shù).protptype.constructor === 該函數(shù)本身

  • 原型減少了不必要的內(nèi)存消耗。

  • 原型鏈指通過(guò)proto不斷向上(父類(lèi)對(duì)象)查找原型對(duì)象的方式,要是找到Object的父類(lèi)對(duì)象null, 還是沒(méi)找到想到的屬性或者方法則會(huì)返回undefined

js創(chuàng)建對(duì)象的幾種方式(常見(jiàn))

  • 工廠模式

  • 構(gòu)造函數(shù)模式

  • 原型模式

  • 組合模式

  • 寄生構(gòu)造模式

繼承

js如何實(shí)現(xiàn)繼承

js如何實(shí)現(xiàn)一個(gè)類(lèi)

js實(shí)現(xiàn)繼承的多種方式

call/apply/bind

  • call、apply和bind都用來(lái)改變this的指向

  • call和apply都是對(duì)函數(shù)直接的調(diào)用,bind()返回一個(gè)函數(shù),需要對(duì)函數(shù)進(jìn)行調(diào)用

  • call和bind可以一個(gè)個(gè)傳入,apply要以數(shù)組的格式傳參

new, this

new操作符

new的模擬實(shí)現(xiàn)

this對(duì)象的理解

this指向

  • this永遠(yuǎn)指向運(yùn)行時(shí)最后調(diào)用它的那個(gè)對(duì)象

  • 在全局變量中this等價(jià)于window對(duì)象,var聲明變量賦值給window,未聲明的變量直接復(fù)制給window

  • 在構(gòu)造函數(shù)中this指向new的對(duì)象

  • 改變this的指向:箭頭函數(shù),call,bind,apply, new實(shí)例化一個(gè)對(duì)象

事件

DOM

  • Document Object Model 文檔對(duì)象模型

DOM事件

  • 事件是用戶或者瀏覽器執(zhí)行某種動(dòng)作,是文檔或者瀏覽器發(fā)生交互的一瞬間,不如點(diǎn)擊一下鼠標(biāo)(click)。html和js之間的交互是通過(guò)事件實(shí)現(xiàn)的。

DOM事件流

  • DOM是一個(gè)樹(shù)型結(jié)構(gòu),當(dāng)html產(chǎn)生事件時(shí),該事件就會(huì)在dom樹(shù)中的根節(jié)點(diǎn)和元素節(jié)點(diǎn)之間傳播,這種事件的傳遞被稱為事件流。

DOM diff

  • 用一個(gè)對(duì)象來(lái)描述DOM樹(shù)即為虛擬DOM。

  • 比對(duì)(diff算法)虛擬DOM和真實(shí)DOM的差異,產(chǎn)生差異補(bǔ)丁對(duì)象,再將差異補(bǔ)丁對(duì)象應(yīng)用到真實(shí)的dom節(jié)點(diǎn)上。因?yàn)椴僮鱠om的代價(jià)是昂貴的,虛擬dom將多次更新的diff內(nèi)容保存到一個(gè)對(duì)象中,這樣可以盡可能地減少dom操作。

事件的三個(gè)階段

  • 捕獲階段、目標(biāo)階段、冒泡階段

  • 在DOM標(biāo)準(zhǔn)事件模型中,是先捕獲后冒泡。但是如果要實(shí)現(xiàn)先冒泡后捕獲的效果, 對(duì)于同一個(gè)事件,監(jiān)聽(tīng)捕獲和冒泡,分別對(duì)應(yīng)相應(yīng)的處理函數(shù),監(jiān)聽(tīng)到捕獲事件,先暫緩執(zhí)行,直到冒泡事件被捕獲后再執(zhí)行捕獲事件。

Event loop

進(jìn)程與線程

  • 線程是一個(gè)程序執(zhí)行的最小單位,一個(gè)進(jìn)程可由一個(gè)或多個(gè)線程組成。不同的進(jìn)程互相獨(dú)立,但是不同的線程之間共享內(nèi)存空間。

執(zhí)行棧

  • 任務(wù)進(jìn)入執(zhí)行棧后分為同步任務(wù)和異步任務(wù)。同步任務(wù)進(jìn)入主線程開(kāi)始執(zhí)行。異步任務(wù)進(jìn)入Event Table并注冊(cè)函數(shù),然后Event Table會(huì)將這個(gè)函數(shù)移入Event Queue。當(dāng)主線程任務(wù)執(zhí)行完畢,會(huì)去Event Queue調(diào)取對(duì)應(yīng)的函數(shù)并放入主線程執(zhí)行。上述過(guò)程不斷重復(fù)就是事件循環(huán)。

為什么js是單線程不是多線程

  • 因?yàn)樽鳛闉g覽器的腳本語(yǔ)言,js主要功能是與用戶交互和操作DOM,多線程會(huì)帶來(lái)很多問(wèn)題,比如在其中一個(gè)線程修改了DOM樹(shù),另一個(gè)線程不變,瀏覽器不知道以哪個(gè)線程為準(zhǔn)。

微任務(wù)/宏任務(wù)

  • 宏任務(wù) js代碼、setTimeout、setInterval、setImmediate

  • 微任務(wù) Promise

  • 事件循環(huán)的順序:進(jìn)入宏任務(wù)后開(kāi)始第一次循環(huán),接著執(zhí)行所有的微任務(wù)。然后再次從宏任務(wù)開(kāi)始。

瀏覽器與node.js的事件循環(huán)

  • process.nextTick(callback)類(lèi)似node.js版的"setTimeout",在事件循環(huán)的下一次循環(huán)中調(diào)用 callback 回調(diào)函數(shù)。

Promise

Promise的基本用法

  • 他是ES6中新增加的一個(gè)類(lèi), 目的是為了管理JS中的異步編程的。

  • Promise 有三個(gè)狀態(tài):pending(準(zhǔn)備狀態(tài):初始化成功、開(kāi)始執(zhí)行異步的任務(wù))、fullfilled(成功狀態(tài))、rejected(失敗狀態(tài))。pending是初始狀態(tài),可以轉(zhuǎn)化為fullfilled和rejected,轉(zhuǎn)化后狀態(tài)不可改變。

  • Promise函數(shù)天生有兩個(gè)參數(shù),resolve(當(dāng)異步操作執(zhí)行成功,執(zhí)行resolve方法),rejected(當(dāng)異步操作失敗,執(zhí)行reject方法) then()方法中有兩個(gè)函數(shù)onFulfilled和onRejected,第一個(gè)傳遞的函數(shù)是resolve,第二個(gè)傳遞的函數(shù)是reject。

  • https://juejin.cn/post/6844903625769091079#heading-9

    <pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="js" cid="n185" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: normal; background-color: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit; background-position: initial initial; background-repeat: initial initial;">class Promise{
    constructor(executor){
    this.state = 'pending';
    this.value = undefined;
    this.reason = undefined;
    this.onResolvedCallbacks = [];
    this.onRejectedCallbacks = [];
    let resolve = value => {
    if (this.state === 'pending') {
    this.state = 'fulfilled';
    this.value = value;
    this.onResolvedCallbacks.forEach(fn=>fn());
    }
    };
    let reject = reason => {
    if (this.state === 'pending') {
    this.state = 'rejected';
    this.reason = reason;
    this.onRejectedCallbacks.forEach(fn=>fn());
    }
    };
    try{
    executor(resolve, reject);
    } catch (err) {
    reject(err);
    }
    }
    then(onFulfilled,onRejected) {
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
    onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err };
    let promise2 = new Promise((resolve, reject) => {
    if (this.state === 'fulfilled') {
    setTimeout(() => {
    try {
    let x = onFulfilled(this.value);
    resolvePromise(promise2, x, resolve, reject);
    } catch (e) {
    reject(e);
    }
    }, 0);
    };
    if (this.state === 'rejected') {
    setTimeout(() => {
    try {
    let x = onRejected(this.reason);
    resolvePromise(promise2, x, resolve, reject);
    } catch (e) {
    reject(e);
    }
    }, 0);
    };
    if (this.state === 'pending') {
    this.onResolvedCallbacks.push(() => {
    setTimeout(() => {
    try {
    let x = onFulfilled(this.value);
    resolvePromise(promise2, x, resolve, reject);
    } catch (e) {
    reject(e);
    }
    }, 0);
    });
    this.onRejectedCallbacks.push(() => {
    setTimeout(() => {
    try {
    let x = onRejected(this.reason);
    resolvePromise(promise2, x, resolve, reject);
    } catch (e) {
    reject(e);
    }
    }, 0)
    });
    };
    });
    return promise2;
    }
    catch(fn){
    return this.then(null,fn);
    }
    }
    function resolvePromise(promise2, x, resolve, reject){
    if(x === promise2){
    return reject(new TypeError('Chaining cycle detected for promise'));
    }
    let called;
    if (x != null && (typeof x === 'object' || typeof x === 'function')) {
    try {
    let then = x.then;
    if (typeof then === 'function') {
    then.call(x, y => {
    if(called)return;
    called = true;
    resolvePromise(promise2, y, resolve, reject);
    }, err => {
    if(called)return;
    called = true;
    reject(err);
    })
    } else {
    resolve(x);
    }
    } catch (e) {
    if(called)return;
    called = true;
    reject(e);
    }
    } else {
    resolve(x);
    }
    }
    //resolve方法
    Promise.resolve = function(val){
    return new Promise((resolve,reject)=>{
    resolve(val)
    });
    }
    //reject方法
    Promise.reject = function(val){
    return new Promise((resolve,reject)=>{
    reject(val)
    });
    }</pre>

    <pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="js" cid="n187" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: normal; background-color: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit; background-position: initial initial; background-repeat: initial initial;">//race方法
    Promise.race = function(promises){
    return new Promise((resolve,reject)=>{
    for(let i=0;i<promises.length;i++){
    promises[i].then(resolve,reject)
    };
    })
    }
    ?</pre>

    <pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="js" cid="n190" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: normal; background-color: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit; background-position: initial initial; background-repeat: initial initial;">//all方法(獲取所有的promise,都執(zhí)行then,把結(jié)果放到數(shù)組,一起返回)
    Promise.all = function(promises){
    let arr = [];
    let i = 0;
    function processData(index,data){
    arr[index] = data;
    i++;
    if(i == promises.length){
    resolve(arr);
    };
    };
    return new Promise((resolve,reject)=>{
    for(let i=0;i<promises.length;i++){
    promises[i].then(data=>{
    processData(i,data);
    },reject);
    };
    });
    }</pre>

    <pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="js" cid="n208" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace; margin-top: 0px; margin-bottom: 20px; font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; white-space: normal; background-color: rgb(51, 51, 51); position: relative !important; padding: 10px 10px 10px 30px; width: inherit; background-position: initial initial; background-repeat: initial initial;">function getData(url) {
    var xhr = new XMLHttpRequest(); // 創(chuàng)建一個(gè)對(duì)象,創(chuàng)建一個(gè)異步調(diào)用的對(duì)象
    xhr.open('get', url, true) // 設(shè)置一個(gè)http請(qǐng)求,設(shè)置請(qǐng)求的方式,url以及驗(yàn)證身份
    xhr.send() //發(fā)送一個(gè)http請(qǐng)求
    xhr.onreadystatechange = function () { //設(shè)置一個(gè)http請(qǐng)求狀態(tài)的函數(shù)
    if (xhr.readyState == 4 && xhr.status ==200) {
    console.log(xhr.responseText) // 獲取異步調(diào)用返回的數(shù)據(jù)
    }
    }
    }
    Promise(getData(url)).resolve(data => data)
    ?
    AJAX狀態(tài)碼:0 - (未初始化)還沒(méi)有調(diào)用send()方法
    1 - (載入)已調(diào)用send方法,正在發(fā)送請(qǐng)求
    2 - (載入完成呢)send()方法執(zhí)行完成
    3 - (交互)正在解析相應(yīng)內(nèi)容
    4 - (完成)響應(yīng)內(nèi)容解析完成,可以在客戶端調(diào)用了
    ?
    ?</pre>

    • 減少http請(qǐng)求數(shù),合理設(shè)置http緩存

    • 合并css圖片,壓縮資源

    • 多圖片的頁(yè)面使用懶加載

    • 減少閉包的使用

    • 減少對(duì)dom的操作

    • 使用svg圖片而不是png圖片

    前端有哪些頁(yè)面優(yōu)化的方法

    • Set本身結(jié)構(gòu)類(lèi)似于數(shù)組,但成員的值唯一。Set利用set構(gòu)造函數(shù)生成set數(shù)據(jù)結(jié)構(gòu),常用來(lái)數(shù)組去重。add 添加元素,delete 刪除元素,has 判斷元素,clear 清除所有元素

    • JavaScript 的對(duì)象(Object),本質(zhì)上是鍵值對(duì)的集合(Hash 結(jié)構(gòu)),但是傳統(tǒng)上只能用字符串當(dāng)作鍵。這給它的使用帶來(lái)了很大的限制。為了解決這個(gè)問(wèn)題,ES6 提供了 Map 數(shù)據(jù)結(jié)構(gòu),使各種類(lèi)型的值(包括對(duì)象)都可以當(dāng)作鍵。也就是說(shuō),Object 結(jié)構(gòu)提供了“字符串—值”的對(duì)應(yīng),Map 結(jié)構(gòu)提供了“值—值”的對(duì)應(yīng),是一種更完善的 Hash 結(jié)構(gòu)實(shí)現(xiàn)。keys()返回所有鍵名的遍歷器,values()返回所有鍵值得遍歷器,entries()返回所有成員的遍歷器,forEach()返回map中所有成員

    Map與Set

    es6 module

    Promise

    • 它的語(yǔ)法標(biāo)志是 ...

    • 以數(shù)組為例,擴(kuò)展運(yùn)算符可以拆開(kāi)這個(gè)數(shù)組,變成一個(gè)元素集合。 擴(kuò)展剩余運(yùn)算符和擴(kuò)展運(yùn)算符的區(qū)別就是,剩余運(yùn)算符會(huì)收集這些集合,放到數(shù)組中。

    剩余/擴(kuò)展運(yùn)算符

    箭頭函數(shù)

    let/const

    es6

    寫(xiě)一個(gè)簡(jiǎn)單的ajax請(qǐng)求

    缺點(diǎn) 1.無(wú)法使用回退按鈕 2.不利于網(wǎng)頁(yè)的SEO 3.不能發(fā)送跨域請(qǐng)求

    ajax的優(yōu)勢(shì) 1.無(wú)刷新頁(yè)面請(qǐng)求,使產(chǎn)品更快,更小更友好 2.服務(wù)器端的任務(wù)轉(zhuǎn)嫁到客戶端處理 3.減輕瀏覽器負(fù)擔(dān),節(jié)約帶寬 4.基于標(biāo)準(zhǔn)化對(duì)象,不需要安裝特定的插件 5.徹底將頁(yè)面與數(shù)據(jù)分離

    • 創(chuàng)建一個(gè)ajax對(duì)象 ,使用XMLHttpRequest這個(gè)函數(shù)創(chuàng)建一個(gè)實(shí)例對(duì)象。

    • 告訴ajax對(duì)象要發(fā)送的請(qǐng)求地址以及請(qǐng)求方式 ,調(diào)用xhr下面的open方法

    • 發(fā)送請(qǐng)求,使用send方法。

    • 獲取服務(wù)器響將要響應(yīng)到客戶端的數(shù)據(jù),使用xhr下的resopnsText屬性就是服務(wù)器響應(yīng)給客戶端的數(shù)據(jù)。

    AJAX實(shí)現(xiàn)

    AJAX

    async await

    Promise.all

    promise.race

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容