2022秋招前端面試題(一)(附答案)

閉包產(chǎn)生的本質(zhì)

當(dāng)前環(huán)境中存在指向父級(jí)作用域的引用

手寫(xiě) bind、apply、call

// call

Function.prototype.call = function (context, ...args) {
  context = context || window;

  const fnSymbol = Symbol("fn");
  context[fnSymbol] = this;

  context[fnSymbol](...args);
  delete context[fnSymbol];
}
復(fù)制代碼
// apply

Function.prototype.apply = function (context, argsArr) {
  context = context || window;

  const fnSymbol = Symbol("fn");
  context[fnSymbol] = this;

  context[fnSymbol](...argsArr);
  delete context[fnSymbol];
}
復(fù)制代碼
// bind

Function.prototype.bind = function (context, ...args) {
  context = context || window;
  const fnSymbol = Symbol("fn");
  context[fnSymbol] = this;

  return function (..._args) {
    args = args.concat(_args);

    context[fnSymbol](...args);
    delete context[fnSymbol];   
  }
}

復(fù)制代碼

函數(shù)防抖

觸發(fā)高頻事件 N 秒后只會(huì)執(zhí)行一次,如果 N 秒內(nèi)事件再次觸發(fā),則會(huì)重新計(jì)時(shí)。

簡(jiǎn)單版:函數(shù)內(nèi)部支持使用 this 和 event 對(duì)象;

function debounce(func, wait) {
    var timeout;
    return function () {
        var context = this;
        var args = arguments;
        clearTimeout(timeout)
        timeout = setTimeout(function(){
            func.apply(context, args)
        }, wait);
    }
}
復(fù)制代碼

使用:

var node = document.getElementById('layout')
function getUserAction(e) {
    console.log(this, e)  // 分別打?。簄ode 這個(gè)節(jié)點(diǎn) 和 MouseEvent
    node.innerHTML = count++;
};
node.onmousemove = debounce(getUserAction, 1000)
復(fù)制代碼

最終版:除了支持 this 和 event 外,還支持以下功能:

  • 支持立即執(zhí)行;
  • 函數(shù)可能有返回值;
  • 支持取消功能;
function debounce(func, wait, immediate) {
    var timeout, result;

    var debounced = function () {
        var context = this;
        var args = arguments;

        if (timeout) clearTimeout(timeout);
        if (immediate) {
            // 如果已經(jīng)執(zhí)行過(guò),不再執(zhí)行
            var callNow = !timeout;
            timeout = setTimeout(function(){
                timeout = null;
            }, wait)
            if (callNow) result = func.apply(context, args)
        } else {
            timeout = setTimeout(function(){
                func.apply(context, args)
            }, wait);
        }
        return result;
    };

    debounced.cancel = function() {
        clearTimeout(timeout);
        timeout = null;
    };

    return debounced;
}
復(fù)制代碼

使用:

var setUseAction = debounce(getUserAction, 10000, true);
// 使用防抖
node.onmousemove = setUseAction

// 取消防抖
setUseAction.cancel()
復(fù)制代碼

symbol 有什么用處

可以用來(lái)表示一個(gè)獨(dú)一無(wú)二的變量防止命名沖突。但是面試官問(wèn)還有嗎?我沒(méi)想出其他的用處就直接答我不知道了,還可以利用 symbol 不會(huì)被常規(guī)的方法(除了 Object.getOwnPropertySymbols 外)遍歷到,所以可以用來(lái)模擬私有變量。

主要用來(lái)提供遍歷接口,布置了 symbol.iterator 的對(duì)象才可以使用 for···of 循環(huán),可以統(tǒng)一處理數(shù)據(jù)結(jié)構(gòu)。調(diào)用之后回返回一個(gè)遍歷器對(duì)象,包含有一個(gè) next 方法,使用 next 方法后有兩個(gè)返回值 value 和 done 分別表示函數(shù)當(dāng)前執(zhí)行位置的值和是否遍歷完畢。

Symbol.for() 可以在全局訪(fǎng)問(wèn) symbol

如何判斷一個(gè)對(duì)象是不是空對(duì)象?

Object.keys(obj).length === 0

手寫(xiě)題:在線(xiàn)編程,getUrlParams(url,key); 就是很簡(jiǎn)單的獲取url的某個(gè)參數(shù)的問(wèn)題,但要考慮邊界情況,多個(gè)返回值等等

什么是作用域?

ES5 中只存在兩種作用域:全局作用域和函數(shù)作用域。在 JavaScript 中,我們將作用域定義為一套規(guī)則,這套規(guī)則用來(lái)管理引擎如何在當(dāng)前作用域以及嵌套子作用域中根據(jù)標(biāo)識(shí)符名稱(chēng)進(jìn)行變量(變量名或者函數(shù)名)查找

AJAX

const getJSON = function(url) {
    return new Promise((resolve, reject) => {
        const xhr = XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP');
        xhr.open('GET', url, false);
        xhr.setRequestHeader('Accept', 'application/json');
        xhr.onreadystatechange = function() {
            if (xhr.readyState !== 4) return;
            if (xhr.status === 200 || xhr.status === 304) {
                resolve(xhr.responseText);
            } else {
                reject(new Error(xhr.responseText));
            }
        }
        xhr.send();
    })
}
復(fù)制代碼

實(shí)現(xiàn)數(shù)組原型方法

forEach

Array.prototype.forEach2 = function(callback, thisArg) {
    if (this == null) {
        throw new TypeError('this is null or not defined')
    }
    if (typeof callback !== "function") {
        throw new TypeError(callback + ' is not a function')
    }
    const O = Object(this)  // this 就是當(dāng)前的數(shù)組
    const len = O.length >>> 0  // 后面有解釋
    let k = 0
    while (k < len) {
        if (k in O) {
            callback.call(thisArg, O[k], k, O);
        }
        k++;
    }
}
復(fù)制代碼

O.length >>> 0 是什么操作?就是無(wú)符號(hào)右移 0 位,那有什么意義嘛?就是為了保證轉(zhuǎn)換后的值為正整數(shù)。其實(shí)底層做了 2 層轉(zhuǎn)換,第一是非 number 轉(zhuǎn)成 number 類(lèi)型,第二是將 number 轉(zhuǎn)成 Uint32 類(lèi)型

map

基于 forEach 的實(shí)現(xiàn)能夠很容易寫(xiě)出 map 的實(shí)現(xiàn):

- Array.prototype.forEach2 = function(callback, thisArg) {
+ Array.prototype.map2 = function(callback, thisArg) {
    if (this == null) {
        throw new TypeError('this is null or not defined')
    }
    if (typeof callback !== "function") {
        throw new TypeError(callback + ' is not a function')
    }
    const O = Object(this)
    const len = O.length >>> 0
-   let k = 0
+   let k = 0, res = []
    while (k < len) {
        if (k in O) {
-           callback.call(thisArg, O[k], k, O);
+           res[k] = callback.call(thisArg, O[k], k, O);
        }
        k++;
    }
+   return res
}
復(fù)制代碼

filter

同樣,基于 forEach 的實(shí)現(xiàn)能夠很容易寫(xiě)出 filter 的實(shí)現(xiàn):

- Array.prototype.forEach2 = function(callback, thisArg) {
+ Array.prototype.filter2 = function(callback, thisArg) {
    if (this == null) {
        throw new TypeError('this is null or not defined')
    }
    if (typeof callback !== "function") {
        throw new TypeError(callback + ' is not a function')
    }
    const O = Object(this)
    const len = O.length >>> 0
-   let k = 0
+   let k = 0, res = []
    while (k < len) {
        if (k in O) {
-           callback.call(thisArg, O[k], k, O);
+           if (callback.call(thisArg, O[k], k, O)) {
+               res.push(O[k])                
+           }
        }
        k++;
    }
+   return res
}
復(fù)制代碼

some

同樣,基于 forEach 的實(shí)現(xiàn)能夠很容易寫(xiě)出 some 的實(shí)現(xiàn):

- Array.prototype.forEach2 = function(callback, thisArg) {
+ Array.prototype.some2 = function(callback, thisArg) {
    if (this == null) {
        throw new TypeError('this is null or not defined')
    }
    if (typeof callback !== "function") {
        throw new TypeError(callback + ' is not a function')
    }
    const O = Object(this)
    const len = O.length >>> 0
    let k = 0
    while (k < len) {
        if (k in O) {
-           callback.call(thisArg, O[k], k, O);
+           if (callback.call(thisArg, O[k], k, O)) {
+               return true
+           }
        }
        k++;
    }
+   return false
}
復(fù)制代碼

reduce

Array.prototype.reduce2 = function(callback, initialValue) {
    if (this == null) {
        throw new TypeError('this is null or not defined')
    }
    if (typeof callback !== "function") {
        throw new TypeError(callback + ' is not a function')
    }
    const O = Object(this)
    const len = O.length >>> 0
    let k = 0, acc

    if (arguments.length > 1) {
        acc = initialValue
    } else {
        // 沒(méi)傳入初始值的時(shí)候,取數(shù)組中第一個(gè)非 empty 的值為初始值
        while (k < len && !(k in O)) {
            k++
        }
        if (k > len) {
            throw new TypeError( 'Reduce of empty array with no initial value' );
        }
        acc = O[k++]
    }
    while (k < len) {
        if (k in O) {
            acc = callback(acc, O[k], k, O)
        }
        k++
    }
    return acc
}
復(fù)制代碼

深淺拷貝

淺拷貝:只考慮對(duì)象類(lèi)型。

function shallowCopy(obj) {
    if (typeof obj !== 'object') return

    let newObj = obj instanceof Array ? [] : {}
    for (let key in obj) {
        if (obj.hasOwnProperty(key)) {
            newObj[key] = obj[key]
        }
    }
    return newObj
}
復(fù)制代碼

簡(jiǎn)單版深拷貝:只考慮普通對(duì)象屬性,不考慮內(nèi)置對(duì)象和函數(shù)。

function deepClone(obj) {
    if (typeof obj !== 'object') return;
    var newObj = obj instanceof Array ? [] : {};
    for (var key in obj) {
        if (obj.hasOwnProperty(key)) {
            newObj[key] = typeof obj[key] === 'object' ? deepClone(obj[key]) : obj[key];
        }
    }
    return newObj;
}
復(fù)制代碼

復(fù)雜版深克?。夯诤?jiǎn)單版的基礎(chǔ)上,還考慮了內(nèi)置對(duì)象比如 Date、RegExp 等對(duì)象和函數(shù)以及解決了循環(huán)引用的問(wèn)題。

const isObject = (target) => (typeof target === "object" || typeof target === "function") && target !== null;

function deepClone(target, map = new WeakMap()) {
    if (map.get(target)) {
        return target;
    }
    // 獲取當(dāng)前值的構(gòu)造函數(shù):獲取它的類(lèi)型
    let constructor = target.constructor;
    // 檢測(cè)當(dāng)前對(duì)象target是否與正則、日期格式對(duì)象匹配
    if (/^(RegExp|Date)$/i.test(constructor.name)) {
        // 創(chuàng)建一個(gè)新的特殊對(duì)象(正則類(lèi)/日期類(lèi))的實(shí)例
        return new constructor(target);  
    }
    if (isObject(target)) {
        map.set(target, true);  // 為循環(huán)引用的對(duì)象做標(biāo)記
        const cloneTarget = Array.isArray(target) ? [] : {};
        for (let prop in target) {
            if (target.hasOwnProperty(prop)) {
                cloneTarget[prop] = deepClone(target[prop], map);
            }
        }
        return cloneTarget;
    } else {
        return target;
    }
}
復(fù)制代碼

事件傳播機(jī)制(事件流)

冒泡和捕獲

為什么需要瀏覽器緩存?

對(duì)于瀏覽器的緩存,主要針對(duì)的是前端的靜態(tài)資源,最好的效果就是,在發(fā)起請(qǐng)求之后,拉取相應(yīng)的靜態(tài)資源,并保存在本地。如果服務(wù)器的靜態(tài)資源沒(méi)有更新,那么在下次請(qǐng)求的時(shí)候,就直接從本地讀取即可,如果服務(wù)器的靜態(tài)資源已經(jīng)更新,那么我們?cè)俅握?qǐng)求的時(shí)候,就到服務(wù)器拉取新的資源,并保存在本地。這樣就大大的減少了請(qǐng)求的次數(shù),提高了網(wǎng)站的性能。這就要用到瀏覽器的緩存策略了。

所謂的瀏覽器緩存指的是瀏覽器將用戶(hù)請(qǐng)求過(guò)的靜態(tài)資源,存儲(chǔ)到電腦本地磁盤(pán)中,當(dāng)瀏覽器再次訪(fǎng)問(wèn)時(shí),就可以直接從本地加載,不需要再去服務(wù)端請(qǐng)求了。

使用瀏覽器緩存,有以下優(yōu)點(diǎn):

  • 減少了服務(wù)器的負(fù)擔(dān),提高了網(wǎng)站的性能
  • 加快了客戶(hù)端網(wǎng)頁(yè)的加載速度
  • 減少了多余網(wǎng)絡(luò)數(shù)據(jù)傳輸

什么是作用域鏈?

首先要了解作用域鏈,當(dāng)訪(fǎng)問(wèn)一個(gè)變量時(shí),編譯器在執(zhí)行這段代碼時(shí),會(huì)首先從當(dāng)前的作用域中查找是否有這個(gè)標(biāo)識(shí)符,如果沒(méi)有找到,就會(huì)去父作用域查找,如果父作用域還沒(méi)找到繼續(xù)向上查找,直到全局作用域?yàn)橹?,而作用域鏈,就是有當(dāng)前作用域與上層作用域的一系列變量對(duì)象組成,它保證了當(dāng)前執(zhí)行的作用域?qū)Ψ显L(fǎng)問(wèn)權(quán)限的變量和函數(shù)的有序訪(fǎng)問(wèn)。

函數(shù)中的arguments是數(shù)組嗎?類(lèi)數(shù)組轉(zhuǎn)數(shù)組的方法了解一下?

是類(lèi)數(shù)組,是屬于鴨子類(lèi)型的范疇,長(zhǎng)得像數(shù)組,

  • ... 運(yùn)算符
  • Array.from
  • Array.prototype.slice.apply(arguments)

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

基本類(lèi)型:Number、Boolean、String、null、undefined、symbol(ES6 新增的),BigInt(ES2020)
引用類(lèi)型:Object,對(duì)象子類(lèi)型(Array,F(xiàn)unction)

什么是文檔的預(yù)解析?

Webkit 和 Firefox 都做了這個(gè)優(yōu)化,當(dāng)執(zhí)行 JavaScript 腳本時(shí),另一個(gè)線(xiàn)程解析剩下的文檔,并加載后面需要通過(guò)網(wǎng)絡(luò)加載的資源。這種方式可以使資源并行加載從而使整體速度更快。需要注意的是,預(yù)解析并不改變 DOM 樹(shù),它將這個(gè)工作留給主解析過(guò)程,自己只解析外部資源的引用,比如外部腳本、樣式表及圖片。

如何防御 XSS 攻擊?

可以看到XSS危害如此之大, 那么在開(kāi)發(fā)網(wǎng)站時(shí)就要做好防御措施,具體措施如下:

  • 可以從瀏覽器的執(zhí)行來(lái)進(jìn)行預(yù)防,一種是使用純前端的方式,不用服務(wù)器端拼接后返回(不使用服務(wù)端渲染)。另一種是對(duì)需要插入到 HTML 中的代碼做好充分的轉(zhuǎn)義。對(duì)于 DOM 型的攻擊,主要是前端腳本的不可靠而造成的,對(duì)于數(shù)據(jù)獲取渲染和字符串拼接的時(shí)候應(yīng)該對(duì)可能出現(xiàn)的惡意代碼情況進(jìn)行判斷。
  • 使用 CSP ,CSP 的本質(zhì)是建立一個(gè)白名單,告訴瀏覽器哪些外部資源可以加載和執(zhí)行,從而防止惡意代碼的注入攻擊。
  1. CSP 指的是內(nèi)容安全策略,它的本質(zhì)是建立一個(gè)白名單,告訴瀏覽器哪些外部資源可以加載和執(zhí)行。我們只需要配置規(guī)則,如何攔截由瀏覽器自己來(lái)實(shí)現(xiàn)。
  2. 通常有兩種方式來(lái)開(kāi)啟 CSP,一種是設(shè)置 HTTP 首部中的 Content-Security-Policy,一種是設(shè)置 meta 標(biāo)簽的方式
  • 對(duì)一些敏感信息進(jìn)行保護(hù),比如 cookie 使用 http-only,使得腳本無(wú)法獲取。也可以使用驗(yàn)證碼,避免腳本偽裝成用戶(hù)執(zhí)行一些操作。

用過(guò) TypeScript 嗎?它的作用是什么?

為 JS 添加類(lèi)型支持,以及提供最新版的 ES 語(yǔ)法的支持,是的利于團(tuán)隊(duì)協(xié)作和排錯(cuò),開(kāi)發(fā)大型項(xiàng)目

瀏覽器本地存儲(chǔ)方式及使用場(chǎng)景

(1)Cookie

Cookie是最早被提出來(lái)的本地存儲(chǔ)方式,在此之前,服務(wù)端是無(wú)法判斷網(wǎng)絡(luò)中的兩個(gè)請(qǐng)求是否是同一用戶(hù)發(fā)起的,為解決這個(gè)問(wèn)題,Cookie就出現(xiàn)了。Cookie的大小只有4kb,它是一種純文本文件,每次發(fā)起HTTP請(qǐng)求都會(huì)攜帶Cookie。

Cookie的特性:

  • Cookie一旦創(chuàng)建成功,名稱(chēng)就無(wú)法修改
  • Cookie是無(wú)法跨域名的,也就是說(shuō)a域名和b域名下的cookie是無(wú)法共享的,這也是由Cookie的隱私安全性決定的,這樣就能夠阻止非法獲取其他網(wǎng)站的Cookie
  • 每個(gè)域名下Cookie的數(shù)量不能超過(guò)20個(gè),每個(gè)Cookie的大小不能超過(guò)4kb
  • 有安全問(wèn)題,如果Cookie被攔截了,那就可獲得session的所有信息,即使加密也于事無(wú)補(bǔ),無(wú)需知道cookie的意義,只要轉(zhuǎn)發(fā)cookie就能達(dá)到目的
  • Cookie在請(qǐng)求一個(gè)新的頁(yè)面的時(shí)候都會(huì)被發(fā)送過(guò)去

如果需要域名之間跨域共享Cookie,有兩種方法:

  1. 使用Nginx反向代理
  2. 在一個(gè)站點(diǎn)登陸之后,往其他網(wǎng)站寫(xiě)Cookie。服務(wù)端的Session存儲(chǔ)到一個(gè)節(jié)點(diǎn),Cookie存儲(chǔ)sessionId

Cookie的使用場(chǎng)景:

  • 最常見(jiàn)的使用場(chǎng)景就是Cookie和session結(jié)合使用,我們將sessionId存儲(chǔ)到Cookie中,每次發(fā)請(qǐng)求都會(huì)攜帶這個(gè)sessionId,這樣服務(wù)端就知道是誰(shuí)發(fā)起的請(qǐng)求,從而響應(yīng)相應(yīng)的信息。
  • 可以用來(lái)統(tǒng)計(jì)頁(yè)面的點(diǎn)擊次數(shù)

(2)LocalStorage

LocalStorage是HTML5新引入的特性,由于有的時(shí)候我們存儲(chǔ)的信息較大,Cookie就不能滿(mǎn)足我們的需求,這時(shí)候LocalStorage就派上用場(chǎng)了。

LocalStorage的優(yōu)點(diǎn):

  • 在大小方面,LocalStorage的大小一般為5MB,可以?xún)?chǔ)存更多的信息
  • LocalStorage是持久儲(chǔ)存,并不會(huì)隨著頁(yè)面的關(guān)閉而消失,除非主動(dòng)清理,不然會(huì)永久存在
  • 僅儲(chǔ)存在本地,不像Cookie那樣每次HTTP請(qǐng)求都會(huì)被攜帶

LocalStorage的缺點(diǎn):

  • 存在瀏覽器兼容問(wèn)題,IE8以下版本的瀏覽器不支持
  • 如果瀏覽器設(shè)置為隱私模式,那我們將無(wú)法讀取到LocalStorage
  • LocalStorage受到同源策略的限制,即端口、協(xié)議、主機(jī)地址有任何一個(gè)不相同,都不會(huì)訪(fǎng)問(wèn)

LocalStorage的常用API:

// 保存數(shù)據(jù)到 localStorage
localStorage.setItem('key', 'value');

// 從 localStorage 獲取數(shù)據(jù)
let data = localStorage.getItem('key');

// 從 localStorage 刪除保存的數(shù)據(jù)
localStorage.removeItem('key');

// 從 localStorage 刪除所有保存的數(shù)據(jù)
localStorage.clear();

// 獲取某個(gè)索引的Key
localStorage.key(index)
復(fù)制代碼

LocalStorage的使用場(chǎng)景:

  • 有些網(wǎng)站有換膚的功能,這時(shí)候就可以將換膚的信息存儲(chǔ)在本地的LocalStorage中,當(dāng)需要換膚的時(shí)候,直接操作LocalStorage即可
  • 在網(wǎng)站中的用戶(hù)瀏覽信息也會(huì)存儲(chǔ)在LocalStorage中,還有網(wǎng)站的一些不常變動(dòng)的個(gè)人信息等也可以存儲(chǔ)在本地的LocalStorage中

(3)SessionStorage

SessionStorage和LocalStorage都是在HTML5才提出來(lái)的存儲(chǔ)方案,SessionStorage 主要用于臨時(shí)保存同一窗口(或標(biāo)簽頁(yè))的數(shù)據(jù),刷新頁(yè)面時(shí)不會(huì)刪除,關(guān)閉窗口或標(biāo)簽頁(yè)之后將會(huì)刪除這些數(shù)據(jù)。

SessionStorage與LocalStorage對(duì)比:

  • SessionStorage和LocalStorage都在本地進(jìn)行數(shù)據(jù)存儲(chǔ)
  • SessionStorage也有同源策略的限制,但是SessionStorage有一條更加嚴(yán)格的限制,SessionStorage只有在同一瀏覽器的同一窗口下才能夠共享;
  • LocalStorage和SessionStorage都不能被爬蟲(chóng)爬取

SessionStorage的常用API:

// 保存數(shù)據(jù)到 sessionStorage
sessionStorage.setItem('key', 'value');

// 從 sessionStorage 獲取數(shù)據(jù)
let data = sessionStorage.getItem('key');

// 從 sessionStorage 刪除保存的數(shù)據(jù)
sessionStorage.removeItem('key');

// 從 sessionStorage 刪除所有保存的數(shù)據(jù)
sessionStorage.clear();

// 獲取某個(gè)索引的Key
sessionStorage.key(index)
復(fù)制代碼

SessionStorage的使用場(chǎng)景

  • 由于SessionStorage具有時(shí)效性,所以可以用來(lái)存儲(chǔ)一些網(wǎng)站的游客登錄的信息,還有臨時(shí)的瀏覽記錄的信息。當(dāng)關(guān)閉網(wǎng)站之后,這些信息也就隨之消除了。

箭頭函數(shù)和普通函數(shù)有啥區(qū)別?箭頭函數(shù)能當(dāng)構(gòu)造函數(shù)嗎?

  • 普通函數(shù)通過(guò) function 關(guān)鍵字定義, this 無(wú)法結(jié)合詞法作用域使用,在運(yùn)行時(shí)綁定,只取決于函數(shù)的調(diào)用方式,在哪里被調(diào)用,調(diào)用位置。(取決于調(diào)用者,和是否獨(dú)立運(yùn)行)
  • 箭頭函數(shù)使用被稱(chēng)為 “胖箭頭” 的操作 => 定義,箭頭函數(shù)不應(yīng)用普通函數(shù) this 綁定的四種規(guī)則,而是根據(jù)外層(函數(shù)或全局)的作用域來(lái)決定 this,且箭頭函數(shù)的綁定無(wú)法被修改(new 也不行)。
    • 箭頭函數(shù)常用于回調(diào)函數(shù)中,包括事件處理器或定時(shí)器
    • 箭頭函數(shù)和 var self = this,都試圖取代傳統(tǒng)的 this 運(yùn)行機(jī)制,將 this 的綁定拉回到詞法作用域
    • 沒(méi)有原型、沒(méi)有 this、沒(méi)有 super,沒(méi)有 arguments,沒(méi)有 new.target
    • 不能通過(guò) new 關(guān)鍵字調(diào)用
      • 一個(gè)函數(shù)內(nèi)部有兩個(gè)方法:[[Call]] 和 [[Construct]],在通過(guò) new 進(jìn)行函數(shù)調(diào)用時(shí),會(huì)執(zhí)行 [[construct]] 方法,創(chuàng)建一個(gè)實(shí)例對(duì)象,然后再執(zhí)行這個(gè)函數(shù)體,將函數(shù)的 this 綁定在這個(gè)實(shí)例對(duì)象上
      • 當(dāng)直接調(diào)用時(shí),執(zhí)行 [[Call]] 方法,直接執(zhí)行函數(shù)體
      • 箭頭函數(shù)沒(méi)有 [[Construct]] 方法,不能被用作構(gòu)造函數(shù)調(diào)用,當(dāng)使用 new 進(jìn)行函數(shù)調(diào)用時(shí)會(huì)報(bào)錯(cuò)。
function foo() {
  return (a) => {
    console.log(this.a);
  }
}

var obj1 = {
  a: 2
}

var obj2 = {
  a: 3 
}

var bar = foo.call(obj1);
bar.call(obj2);
復(fù)制代碼

點(diǎn)擊刷新按鈕或者按 F5、按 Ctrl+F5 (強(qiáng)制刷新)、地址欄回車(chē)有什么區(qū)別?

  • 點(diǎn)擊刷新按鈕或者按 F5: 瀏覽器直接對(duì)本地的緩存文件過(guò)期,但是會(huì)帶上If-Modifed-Since,If-None-Match,這就意味著服務(wù)器會(huì)對(duì)文件檢查新鮮度,返回結(jié)果可能是 304,也有可能是 200。
  • 用戶(hù)按 Ctrl+F5(強(qiáng)制刷新): 瀏覽器不僅會(huì)對(duì)本地文件過(guò)期,而且不會(huì)帶上 If-Modifed-Since,If-None-Match,相當(dāng)于之前從來(lái)沒(méi)有請(qǐng)求過(guò),返回結(jié)果是 200。
  • 地址欄回車(chē): 瀏覽器發(fā)起請(qǐng)求,按照正常流程,本地檢查是否過(guò)期,然后服務(wù)器檢查新鮮度,最后返回內(nèi)容。
?著作權(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)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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