JS面試題
- js基本類型和引用類型
- 說說寫JavaScript的基本規(guī)范杯瞻?
- js如何判斷一個(gè)對象是數(shù)組
- 怎么判斷兩個(gè)對象相等
- "=="和"==="的不同
- js對數(shù)組操作的常用方法有哪些扭吁?
- split() join() 的區(qū)別
- js 拷貝
- 原型和原型鏈
- 什么是閉包
- 事件循環(huán)機(jī)制(event loop)
- require和import區(qū)別
- 怎么理解js中的內(nèi)存泄露
- js延遲加載的方式有哪些球碉?
- 如何阻止事件冒泡
- 淺談setTimeout 和 setInterval
- JavaScript作用域鏈
- Ajax使用
- 談?wù)則his的理解
- 什么是window對象? 什么是document對象?
- null蜓斧,undefined的區(qū)別?
- new操作符具體干了什么呢?
- 同步和異步的區(qū)別?
- 回流與重繪
- DOM操作
- 數(shù)組對象有哪些原生方法睁冬,列舉一下
- 哪些操作會(huì)造成內(nèi)存泄漏
- 請描述一下cookie,sessionStorage和localStorage的區(qū)別
- http狀態(tài)碼有那些挎春?分別代表是什么意思?列舉2-3個(gè)熟悉的狀態(tài)碼
- 一個(gè) http 請求由什么組成豆拨?
- http 協(xié)議的 三次握手/四次揮手直奋,可以描述一下嗎?
- ajax請求的時(shí)候get 和post方式的區(qū)別?
- 什么是防抖和節(jié)流施禾?有什么區(qū)別帮碰?如何實(shí)現(xiàn)?
js面試題解析
js基本類型和引用類型
- null(空)
- undefined(未聲明)
- number(數(shù)字)
- string(字符串)
- object(對象)
- boolean(布爾值)
- symbol(符號拾积,es6新增)
基本數(shù)據(jù)類型:Undefined殉挽、Null、Boolean拓巧、String斯碌、Number、Symbol (es6)肛度。
引用類型:Object傻唾。Object可以細(xì)分為:Object 類型、Array 類型、Date 類型冠骄、RegExp 類型伪煤、Function 類型
說說寫JavaScript的基本規(guī)范?
- 不要在同一行聲明多個(gè)變量
- 使用 ===或!==來比較true/false或者數(shù)值
- switch必須帶有default分支
- 函數(shù)應(yīng)該有返回值
- for if else 必須使用大括號
- 語句結(jié)束加分號
- 命名要有意義凛辣,使用駝峰命名法
js如何判斷一個(gè)對象是數(shù)組
1.typeof操作符
- 利用typeof除了array和null判斷為object外抱既,其他的都可以正常判斷
2.instanceof操作符
var arr = [1,2,3,1];
console.log(arr instanceof Array); // true
var fun = function(){};
console.log(fun instanceof Function); // true
3.對象的constructor 屬性
var arr = [1,2,3,1];
console.log(arr.constructor === Array); // true
var fun = function(){};
console.log(arr.constructor === Function); // true
4.使用 Object.prototype.toString 來判斷是否是數(shù)組
Object.prototype.toString.call( [] ) === ``'[object Array]'` `// true`
Object.prototype.toString.call( ``function``(){} ) === ``'[object Function]'` `// true
這里使用call來使 toString 中 this 指向 obj。進(jìn)而完成判斷
5.Array.isArray()
Array.isArray([]) ``// true
6.使用 原型鏈 來完成判斷
[].__proto__ === Array.prototype ``// true` `var` `fun = ``function``(){}``fun.__proto__ === Function.prototype ``// true
怎么判斷兩個(gè)對象相等
JSON.stringify(obj)==JSON.stringify(obj); //true
"=="和"==="的不同
- 前者會(huì)自動(dòng)轉(zhuǎn)換類型,再判斷是否相等
具體如下:
一扁誓、首先看雙等號前后有沒有NaN防泵,如果存在NaN,一律返回false蝗敢。
二捷泞、再看雙等號前后有沒有布爾,有布爾就將布爾轉(zhuǎn)換為數(shù)字(false是0寿谴,true是1)
三锁右、接著看雙等號前后有沒有字符串, 有三種情況:
1、對方是對象讶泰,對象使用toString()或者valueOf()進(jìn)行轉(zhuǎn)換咏瑟;
2、對方是數(shù)字峻厚,字符串轉(zhuǎn)數(shù)字响蕴;(前面已經(jīng)舉例)
3、對方是字符串惠桃,直接比較浦夷;
4、其他返回false
四辜王、如果是數(shù)字劈狐,對方是對象,對象取valueOf()或者toString()進(jìn)行比較, 其他一律返回false
五呐馆、null, undefined不會(huì)進(jìn)行類型轉(zhuǎn)換, 但它們倆相等- 后者不會(huì)自動(dòng)類型轉(zhuǎn)換肥缔,直接去比較
js對數(shù)組操作的常用方法有哪些?
1汹来、shift():刪除原數(shù)組第一項(xiàng)续膳,并返回刪除元素的值;如果數(shù)組為空則返回undefine收班。這里是0
2坟岔、unshift(3,4):把參數(shù)加載數(shù)組的前面,并返回新數(shù)組長度∷よ耄現(xiàn)在list:中是3,4,0,1,2
3社付、pop():刪除最后一項(xiàng),并返回刪除元素的值;如果數(shù)組為空則返回undefine。這里是2.
4鸥咖、push(3):將參數(shù)加載到數(shù)組的最后燕鸽,并返回新數(shù)組長度,現(xiàn)在List中時(shí):0,1,2,3
5啼辣、concat(3,4):把兩個(gè)數(shù)組拼接起來啊研,返回合并后的新數(shù)組,原數(shù)組木變。
6熙兔、splice(start,deleteCount,val1,val2,...):從start位置開始刪除deleteCount項(xiàng)悲伶,并從該位置起插入val1,val2,...
7艾恼、reverse:并返回翻轉(zhuǎn)后的原數(shù)組住涉,原數(shù)組翻轉(zhuǎn)了
8、sort(orderfunction):按指定的參數(shù)對數(shù)組進(jìn)行排序 var a = [1,2,3,4,5]; var b = a.sort(); //a:[1,2,3,4,5] b:[1,2,3,4,5]
9钠绍、slice(start,end):返回從原數(shù)組中指定開始下標(biāo)到結(jié)束下標(biāo)之間的項(xiàng)組成的新數(shù)組舆声,原數(shù)組木變,索引從0開始
10柳爽、join 將數(shù)組轉(zhuǎn)換成字符串并返回字符串.將數(shù)組中所有元素以參數(shù)作為分隔符放入一個(gè)字符媳握,原數(shù)組木變
11、indexOf 數(shù)組元素索引磷脯,并返回元素索引蛾找,不存在返回-1,索引從0開始
改變原數(shù)組的:
shift,unshift赵誓,pop打毛,push,reverse俩功,sort幻枉,splice
不改變原數(shù)組的:
concat,join,slice:slice(start,end),map,filter,some,every
split() join() 的區(qū)別
前者是將字符串切割成數(shù)組的形式诡蜓,后者是將數(shù)組轉(zhuǎn)換成字符串
js 拷貝
分為深拷貝和淺拷貝熬甫。
- 淺拷貝: 只對基本數(shù)據(jù)類型進(jìn)行拷貝,方法有:Object.assign() 蔓罚、es6的結(jié)構(gòu)賦值椿肩、數(shù)組的slice、concat方法豺谈、展開運(yùn)算符郑象、Array.from。
- 深拷貝:對所有數(shù)據(jù)類型進(jìn)行真正的拷貝核无,方法有:利用JSON.stringify() 和JSON.parse()扣唱、利用遞歸實(shí)現(xiàn)。
原型和原型鏈
- 在JavaScript中萬物都是對象,對象和對象之間也有關(guān)系噪沙,并不是孤立存在的炼彪。對象之間的繼承關(guān)系,在JavaScript中是通過prototype對象指向父類對象正歼,直到指向Object對象為止辐马,這樣就形成了一個(gè)原型指向的鏈條,專業(yè)術(shù)語稱之為原型鏈局义。
- 原型也是一個(gè)對象喜爷,通過原型可以實(shí)現(xiàn)對象的屬性繼承,JavaScript的對象中都包含了一個(gè)”[[Prototype]]”內(nèi)部屬性萄唇,這個(gè)屬性所對應(yīng)的就是該對象的原型檩帐。
什么是閉包
要了解閉包,要先了解什么是作用域(作用域就是變量與函數(shù)的可訪問范圍: 任何地方都能訪問到的對象擁有全局作用域另萤,局部作用域一般只在固定的代碼片段內(nèi)可訪問到湃密,最常見的例如函數(shù)內(nèi)部),函數(shù)內(nèi)部可以直接讀取全局變量四敞,但是函數(shù)外部是無法讀取函數(shù)內(nèi)的局部變量泛源,那么如何可以在外部讀取到函數(shù)內(nèi)部的變量,可以通過函數(shù)內(nèi)部的函數(shù)實(shí)現(xiàn)忿危,在這個(gè)內(nèi)部函數(shù)中去訪問函數(shù)內(nèi)部的變量达箍,并將其返回,這就形成了閉包铺厨,即能夠讀取其他函數(shù)內(nèi)部變量的函數(shù)缎玫。閉包就是能夠讀取其他函數(shù)內(nèi)部變量的函數(shù)
function test() {
const z = 1
return function() {
console.log('z',z)
}
}
const fn = test()
const z = 2
fn()
// 'z', 1
返回的是函數(shù)位置指向最靠近的上一級的z的值
事件循環(huán)機(jī)制(event loop)
- js代碼執(zhí)行時(shí),先按代碼順序?qū)⑼饺蝿?wù)壓入主執(zhí)行棧中執(zhí)行
- 遇到異步任務(wù)則先將異步任務(wù)壓入對應(yīng)的任務(wù)隊(duì)列中(宏隊(duì)列或微隊(duì)列)
- 同步任務(wù)執(zhí)行完畢后努释,查看微隊(duì)列碘梢,將微任務(wù)一一取出進(jìn)入主執(zhí)行棧中執(zhí)行
- 微任務(wù)隊(duì)列清空后,再查看宏隊(duì)列伐蒂,只取出第一個(gè)宏任務(wù)執(zhí)行煞躬,執(zhí)行完一個(gè)宏任務(wù)后,回到第三步的操作 這個(gè)過程是循環(huán)不斷的逸邦,所以整個(gè)的這種運(yùn)行機(jī)制又稱為Event Loop(事件循環(huán))
require和import區(qū)別
- import和require都是被模塊化使用
- require是運(yùn)行時(shí)調(diào)用恩沛,所以可以隨處引入
- import是編譯時(shí)調(diào)用,必須放在文件開頭引入缕减,目前部分瀏覽器不支持雷客,需要用babel把es6轉(zhuǎn)成es5再執(zhí)行說
怎么理解js中的內(nèi)存泄露
定義:程序不需要的內(nèi)存,由于某些原因其不會(huì)返回到操作系統(tǒng)或者可用內(nèi)存池中桥狡。 內(nèi)存泄露會(huì)導(dǎo)致(運(yùn)行緩慢 搅裙,高延遲皱卓,崩潰)的問題
常見的導(dǎo)致內(nèi)存泄露的原因有:
- 意外的全局變量
- 被遺忘的計(jì)時(shí)器或回調(diào)函數(shù)
- 脫離文檔的DOM的引用
- 閉包
js延遲加載的方式有哪些?
defer和async部逮、動(dòng)態(tài)創(chuàng)建DOM方式(創(chuàng)建script娜汁,插入到DOM中,加載完畢后callBack)兄朋、按需異步載入js
- 沒有 defer 或 async掐禁,瀏覽器會(huì)立即加載并執(zhí)行指定的腳本,“立即”指的是在渲染該 script 標(biāo)簽之下的文檔元素之前颅和,也就是說不等待后續(xù)載入的文檔元素傅事,讀到就加載并執(zhí)行。
- 有 async峡扩,加載和渲染后續(xù)文檔元素的過程將和 script.js 的加載與執(zhí)行并行進(jìn)行(異步)蹭越。
- 有 defer,加載后續(xù)文檔元素的過程將和 script.js 的加載并行進(jìn)行(異步)有额,但是 script.js 的執(zhí)行要在所有元素解析完成之后般又,DOMContentLoaded 事件觸發(fā)之前完成彼绷。
如何阻止事件冒泡
ie:阻止冒泡ev.cancelBubble = true;非IE ev.stopPropagation();
如何阻止默認(rèn)事件
(1)return false巍佑;(2) ev.preventDefault();
淺談setTimeout 和 setInterval
- 前者是在一定時(shí)間過后將函數(shù)添加至執(zhí)行隊(duì)列,執(zhí)行時(shí)間=延遲時(shí)間+之前函數(shù)代碼執(zhí)行時(shí)間+執(zhí)行函數(shù)時(shí)間寄悯。
- 后者是不管前一次是否執(zhí)行完畢萤衰,每隔一定時(shí)間重復(fù)執(zhí)行,用于精準(zhǔn)執(zhí)行互相沒有影響的重復(fù)操作猜旬。
Javascript作用鏈域
作用域鏈的原理和原型鏈很類似脆栋,如果這個(gè)變量在自己的作用域中沒有,那么它會(huì)尋找父級的洒擦,直到最頂層椿争。
注意:JS沒有塊級作用域,若要形成塊級作用域熟嫩,可通過(function(){})()秦踪;立即執(zhí)行的形式實(shí)現(xiàn)。
Ajax使用
全稱 : Asynchronous Javascript And XML
所謂異步掸茅,就是向服務(wù)器發(fā)送請求的時(shí)候椅邓,我們不必等待結(jié)果,而是可以同時(shí)做其他的事情昧狮,等到有了結(jié)果它自己會(huì)根據(jù)設(shè)定進(jìn)行后續(xù)操作景馁,與此同時(shí),頁面是不會(huì)發(fā)生整頁刷新的逗鸣,提高了用戶體驗(yàn)合住。
創(chuàng)建Ajax的過程:
- 創(chuàng)建XMLHttpRequest對象(異步調(diào)用對象)
var xhr = new XMLHttpRequest();
- 創(chuàng)建新的Http請求(方法绰精、URL、是否異步)
xhr.open(‘get’,’example.php’,false);
- 設(shè)置響應(yīng)HTTP請求狀態(tài)變化的函數(shù)透葛。
onreadystatechange事件中readyState屬性等于4茬底。響應(yīng)的HTTP狀態(tài)為200(OK)或者304(Not Modified)。- 發(fā)送http請求
xhr.send(data);
- 獲取異步調(diào)用返回的數(shù)據(jù)
注意:
1 頁面初次加載時(shí)获洲,盡量在web服務(wù)器一次性輸出所有相關(guān)的數(shù)據(jù)阱表,只在頁面加載完成之后,用戶進(jìn)行操作時(shí)采用ajax進(jìn)行交互贡珊。
2 同步ajax在IE上會(huì)產(chǎn)生頁面假死的問題最爬。所以建議采用異步ajax。
3 盡量減少ajax請求次數(shù)
4 ajax安全問題门岔,對于敏感數(shù)據(jù)在服務(wù)器端處理爱致,避免在客戶端處理過濾。對于關(guān)鍵業(yè)務(wù)邏輯代碼也必須放在服務(wù)器端處理寒随。
談?wù)則his的理解
- this總是指向函數(shù)的直接調(diào)用者(而非間接調(diào)用者)
- 如果有new關(guān)鍵字糠悯,this指向new出來的那個(gè)對象
- 在事件中,this指向目標(biāo)元素妻往,特殊的是IE的attachEvent中的this總是指向全局對象window互艾。
什么是window對象? 什么是document對象?
window對象代表瀏覽器中打開的一個(gè)窗口。document對象代表整個(gè)html文檔讯泣。實(shí)際上纫普,document對象是window對象的一個(gè)屬性。
null好渠,undefined的區(qū)別昨稼?
null表示一個(gè)對象被定義了,但存放了空指針拳锚,轉(zhuǎn)換為數(shù)值時(shí)為0假栓。
undefined表示聲明的變量未初始化,轉(zhuǎn)換為數(shù)值時(shí)為NAN霍掺。
typeof(null) -- object;
typeof(undefined) -- undefined
new操作符具體干了什么呢?
- 創(chuàng)建一個(gè)空對象匾荆,并且 this 變量引用該對象,同時(shí)還繼承了該函數(shù)的原型抗楔。
- 屬性和方法被加入到 this 引用的對象中棋凳。
- 新創(chuàng)建的對象由 this 所引用,并且最后隱式的返回 this 连躏。
同步和異步的區(qū)別?
同步的概念在操作系統(tǒng)中:不同進(jìn)程協(xié)同完成某項(xiàng)工作而先后次序調(diào)整(通過阻塞剩岳、喚醒等方式),同步強(qiáng)調(diào)的是順序性入热,誰先誰后拍棕。異步不存在順序性晓铆。
- 同步:瀏覽器訪問服務(wù)器,用戶看到頁面刷新绰播,重新發(fā)請求骄噪,等請求完,頁面刷新蠢箩,新內(nèi)容出現(xiàn)链蕊,用戶看到新內(nèi)容之后進(jìn)行下一步操作。
- 異步:瀏覽器訪問服務(wù)器請求谬泌,用戶正常操作滔韵,瀏覽器在后端進(jìn)行請求。等請求完掌实,頁面不刷新陪蜻,新內(nèi)容也會(huì)出現(xiàn),用戶看到新內(nèi)容贱鼻。
回流與重繪
當(dāng)渲染樹中的一部分(或全部)因?yàn)樵氐囊?guī)模尺寸宴卖,布局,隱藏等改變而需要重新構(gòu)建邻悬。這就稱為回流(reflow)症昏。每個(gè)頁面至少需要一次回流,就是在頁面第一次加載的時(shí)候拘悦。在回流的時(shí)候齿兔,瀏覽器會(huì)使渲染樹中受到影響的部分失效,并重新構(gòu)造這部分渲染樹础米。完成回流后,瀏覽器會(huì)重新繪制受影響的部分到屏幕中添诉,該過程成為重繪
DOM操作
- 創(chuàng)建新節(jié)點(diǎn)
createDocumentFragment() //創(chuàng)建一個(gè)DOM片段
createElement() //創(chuàng)建一個(gè)具體的元素
createTextNode() //創(chuàng)建一個(gè)文本節(jié)點(diǎn)- 添加屁桑、移除、替換栏赴、插入
appendChild()
removeChild()
replaceChild()
insertBefore() //在已有的子節(jié)點(diǎn)前插入一個(gè)新的子節(jié)點(diǎn)- 查找
getElementsByTagName() //通過標(biāo)簽名稱
getElementsByName() //通過元素的Name屬性的值(IE容錯(cuò)能力較強(qiáng)蘑斧,會(huì)得到一個(gè)數(shù)組,其中包括id等于name值的)
getElementById() //通過元素Id须眷,唯一性
數(shù)組對象有哪些原生方法竖瘾,列舉一下
pop、push花颗、shift捕传、unshift、splice扩劝、reverse庸论、sort职辅、concat、join聂示、slice域携、toString、indexOf鱼喉、lastIndexOf秀鞭、reduce、reduceRight扛禽、forEach气筋、map、filter旋圆、every宠默、some
哪些操作會(huì)造成內(nèi)存泄漏
全局變量、閉包灵巧、DOM清空或刪除時(shí)搀矫,事件未清除、子元素存在引用
請描述一下cookie,sessionStorage和localStorage的區(qū)別
- localStorage長期存儲(chǔ)數(shù)據(jù)刻肄,瀏覽器關(guān)閉數(shù)據(jù)后不丟失瓤球;
- sessionStorage數(shù)據(jù)在瀏覽器關(guān)閉后自動(dòng)刪除;
- cookie是網(wǎng)站為了標(biāo)識用戶身份而存儲(chǔ)在用戶本地終端(Client Side)上的數(shù)據(jù)(通常經(jīng)過加密)敏弃。cookie始終在同源的http請求中攜帶(即使不需要)都會(huì)在瀏覽器和服務(wù)器端間來回傳遞卦羡。session storage和local storage不會(huì)自動(dòng)把數(shù)據(jù)發(fā)給服務(wù)器,僅在本地保存麦到;
- 存儲(chǔ)大新潭:cookie數(shù)據(jù)大小不會(huì)超過4K,session storage和local storage雖然也有存儲(chǔ)大小的限制瓶颠,但比cookie大得多拟赊,可以達(dá)到5M或者更多;
- 有期時(shí)間:local storage存儲(chǔ)持久數(shù)據(jù)粹淋,瀏覽器關(guān)閉后數(shù)據(jù)不丟失吸祟,除非自動(dòng)刪除數(shù)據(jù)。session storage數(shù)據(jù)在當(dāng)前瀏覽器窗口關(guān)閉后自動(dòng)刪除桃移。cookie 設(shè)置的cookie過期時(shí)間之前一直有效屋匕,即使窗口或者瀏覽器關(guān)閉;
http狀態(tài)碼有那些借杰?分別代表是什么意思过吻?列舉2-3個(gè)熟悉的狀態(tài)碼
當(dāng)用戶在瀏覽網(wǎng)頁的時(shí)候,瀏覽器會(huì)返回一個(gè)htttp狀態(tài)碼第步,主要是用來響應(yīng)瀏覽器的請求疮装。
- 200 OK 請求正常處理完畢
- 204 No Content 請求成功處理缘琅,沒有實(shí)體的主體返回
- 301 Moved Permanently 永久重定向,資源已永久分配新URI
- 302 Found 臨時(shí)重定向廓推,資源已臨時(shí)分配新URI
- 400 Bad Request 請求報(bào)文語法錯(cuò)誤或參數(shù)錯(cuò)誤
- 401 Unauthorized 要通過HTTP認(rèn)證刷袍,或認(rèn)證失敗
- 403 Forbidden 請求資源被拒絕
- 404 Not Found 無法找到請求資源(服務(wù)器無理由拒絕)
- 500 Internal Server Error 服務(wù)器故障或Web應(yīng)用故障
- 503 Service Unavailable 服務(wù)器超負(fù)載或停機(jī)維護(hù)你可以關(guān)閉;
一個(gè) http 請求由什么組成樊展?
請求的方法:post呻纹,get
正在請求的URL:請求的地址
請求頭:客戶端環(huán)境信息,身份驗(yàn)證信息
請求體:表單信息等
http協(xié)議的 三次握手/四次揮手专缠,可以描述一下嗎雷酪?
http的三次握手和四次揮手:
瀏覽器在給服,務(wù)器傳輸數(shù)據(jù)之前涝婉,有三次握手哥力,握手成功之后,才可以傳輸數(shù)據(jù)
- 瀏覽器需要先發(fā)送SYN碼墩弯,客戶端請求和服務(wù)器建立連接吩跋;
- 服務(wù)器接收到SYN碼,再發(fā)送給客戶端SYN+ACK碼渔工,我可以建立連接锌钮;
- 客戶端接收到ACK碼,驗(yàn)證這個(gè)ACK是否正確引矩,如果正確則客戶端和服務(wù)端則建立起數(shù)據(jù)連接梁丘;雙方的數(shù)據(jù)發(fā)送通道都將開啟;
四次揮手:
- 當(dāng)客戶端無數(shù)據(jù)要傳輸了旺韭,會(huì)發(fā)送FIN碼告訴服務(wù)器氛谜,我發(fā)送完畢了;
- 當(dāng)服務(wù)器接收完畢后茂翔,告訴客戶端ACK碼混蔼,告訴客戶端你可以把數(shù)據(jù)通道關(guān)閉了;
- 當(dāng)服務(wù)器發(fā)送完畢之后珊燎,也會(huì)發(fā)送FIN碼,告訴瀏覽器遵湖,數(shù)據(jù)發(fā)送完畢悔政;
- 當(dāng)客戶端接收完畢 之后,同樣發(fā)送ACK碼延旧,告訴服務(wù)器谋国,數(shù)據(jù)接收 完畢,
ajax請求的時(shí)候get 和post方式的區(qū)別?
1.使用Get請求時(shí),參數(shù)在URL中顯示,而使用Post方式,則不會(huì)顯示出來
2.使用Get請求發(fā)送數(shù)據(jù)量小,Post請求發(fā)送數(shù)據(jù)量大
什么是防抖和節(jié)流迁沫?有什么區(qū)別芦瘾?如何實(shí)現(xiàn)捌蚊?
防抖:
觸發(fā)高頻事件后n秒內(nèi)函數(shù)只會(huì)執(zhí)行一次,如果n秒內(nèi)高頻事件再次被觸發(fā)近弟,則重新計(jì)算時(shí)間
- 舉個(gè)栗子
每次觸發(fā)事件時(shí)都取消之前的延時(shí)調(diào)用方法
function debounce(fn) {
let timeout = null; // 創(chuàng)建一個(gè)標(biāo)記用來存放定時(shí)器的返回值
return function () {
clearTimeout(timeout); // 每當(dāng)用戶輸入的時(shí)候把前一個(gè) setTimeout clear 掉
timeout = setTimeout(() => { // 然后又創(chuàng)建一個(gè)新的 setTimeout, 這樣就能保證輸入字符后的 interval 間隔內(nèi)如果還有字符輸入的話缅糟,就不會(huì)執(zhí)行 fn 函數(shù)
fn.apply(this, arguments);
}, 500);
};
}
function sayHi() {
console.log('防抖成功');
}
var inp = document.getElementById('inp');
inp.addEventListener('input', debounce(sayHi)); // 防抖
節(jié)流:
高頻事件觸發(fā),但在n秒內(nèi)只會(huì)執(zhí)行一次祷愉,所以節(jié)流會(huì)稀釋函數(shù)的執(zhí)行頻率
- 舉個(gè)栗子
每次觸發(fā)事件時(shí)都判斷當(dāng)前是否有等待執(zhí)行的延時(shí)函數(shù)
function throttle(fn) {
let canRun = true; // 通過閉包保存一個(gè)標(biāo)記
return function () {
if (!canRun) return; // 在函數(shù)開頭判斷標(biāo)記是否為true窗宦,不為true則return
canRun = false; // 立即設(shè)置為false
setTimeout(() => { // 將外部傳入的函數(shù)的執(zhí)行放在setTimeout中
fn.apply(this, arguments);
// 最后在setTimeout執(zhí)行完畢后再把標(biāo)記設(shè)置為true(關(guān)鍵)表示可以執(zhí)行下一次循環(huán)了。當(dāng)定時(shí)器沒有執(zhí)行的時(shí)候標(biāo)記永遠(yuǎn)是false二鳄,在開頭被return掉
canRun = true;
}, 500);
};
}
function sayHi(e) {
console.log(e.target.innerWidth, e.target.innerHeight);
}
window.addEventListener('resize', throttle(sayHi));
持續(xù)更新中......