摘要:靜態(tài)作用域與動態(tài)作用域靜態(tài)作用域函數(shù)的作用域基于函數(shù)創(chuàng)建的位置。采用的是詞法作用域,也稱為靜態(tài)作用域??梢越俪终麄€對象,并返回一個新的對象。防誤觸延緩執(zhí)行立即執(zhí)行節(jié)流所謂節(jié)流,就是指連續(xù)觸發(fā)事件但是在秒中只執(zhí)行一次函數(shù)。
在這里記錄著每天自己遇到的一道印象深刻的前端問題,以及一道生活中隨處可見的小問題。
強(qiáng)迫自己形成積累的習(xí)慣,鞭撻自己不斷前行,共同學(xué)習(xí)。
Github 地址
2019/04/15 - 2019/04/21 1. 寫一個亂序函數(shù) ?遍歷數(shù)組元素,然后將當(dāng)前元素與以后隨機(jī)位置的元素進(jìn)行交換。
function shuffle(a) { for (let i = a.length; i; i--) { let j = Math.floor(Math.random() * i); // es6語法 [a[i - 1], a[j]] = [a[j], a[i - 1]]; } return a; }2. 什么是惰性函數(shù)?
惰性函數(shù)就是返回一個重寫函數(shù)。For example:
var foo = function() { var t = new Date(); foo = function() { return t; }; return foo(); }; foo();3. 靜態(tài)作用域與動態(tài)作用域 ?
靜態(tài)作用域 —— 函數(shù)的作用域基于函數(shù)創(chuàng)建的位置。
動態(tài)作用域 —— 函數(shù)的作用域基于函數(shù)的使用位置。
var value = 1; function foo() { console.log(value); } function bar() { var value = 2; foo(); } bar(); // 輸出 1 。JavaScript 采用的是詞法作用域,也稱為靜態(tài)作用域。相同的,動態(tài)作用域此代碼應(yīng)該輸出 24. 手寫一個 function call()函數(shù) ?
Function.prototype.call2 = function(context, ...args) { // 因為傳進(jìn)來的 context 有可能是 null context = context || window; // Function.prototype this 為當(dāng)前運行的函數(shù) // 讓 fn 的上下文為 context context.fn = this; const result = context.fn(...args); delete context.fn; return result; };5. Vue 組件中的 name 屬性的作用 ?
組件在全局用 Vue.component() 注冊時,全局 ID 自動作為組件的 name。
指定 name 選項的另一個好處是便于調(diào)試。有名字的組件有更友好的警告信息。另外,當(dāng)在有 vue-devtools,未命名組件將顯示成
hash 路由
hash 路由一個明顯的標(biāo)志是帶有#,我們主要是通過監(jiān)聽 url 中的 hash 變化來進(jìn)行路由跳轉(zhuǎn)。(window.addEventListener("hashchange", this.refresh, false);)
hash 的優(yōu)勢就是兼容性更好,在老版 IE 中都有運行,問題在于 url 中一直存在#不夠美觀,而且 hash 路由更像是 Hack 而非標(biāo)準(zhǔn),相信隨著發(fā)展更加標(biāo)準(zhǔn)化的 History API 會逐步蠶食掉 hash 路由的市場。
history 路由
history 路由使用 History API 來實現(xiàn),具體有:
window.history.back(); // 后退 window.history.forward(); // 前進(jìn) window.history.go(-3); // 后退三個頁面
history.pushState用于在瀏覽歷史中添加歷史記錄, history.replaceState方法的參數(shù)與pushState方法一模一樣,區(qū)別是它修改瀏覽歷史中當(dāng)前紀(jì)錄,而非添加記錄,同樣不觸發(fā)跳轉(zhuǎn)。
7. Vue 的響應(yīng)式原理中 Object.defineProperty 有什么缺陷?為什么在 Vue3.0 采用了 Proxy,拋棄了 Object.defineProperty?Object.defineProperty 無法監(jiān)控到數(shù)組下標(biāo)的變化,導(dǎo)致通過數(shù)組下標(biāo)添加元素,不能實時響應(yīng);
Object.defineProperty 只能劫持對象的屬性,從而需要對每個對象,每個屬性進(jìn)行遍歷,如果,屬性值是對象,還需要深度遍歷。Proxy 可以劫持整個對象,并返回一個新的對象。
Proxy 不僅可以代理對象,還可以代理數(shù)組。還可以代理動態(tài)增加的屬性。
2019/04/08 - 2019/04/14 4. 寫一個“終極類型”判斷函數(shù)?function type(obj) { var toString = Object.prototype.toString; var toType = {}; var typeArr = [ "Undefined", "Null", "Boolean", "Number", "String", "Object", "Array", "Function", "Date", "RegExp", "Error", "Arguments" ]; // 這里利用了object 對象toString() 后 值為 "[object Array]" 等情況進(jìn)行判斷 typeArr.map(function(item, index) { toType["[object " + item + "]"] = item.toLowerCase(); }); return typeof obj !== "object" ? typeof obj : toType[toString.call(obj)]; }2. 寫一個函數(shù),判斷各種類型的不同變量是否相等,即“終極等于”函數(shù)?
const equals = (a, b) => { if (a === b) return true; // 時間的判斷 if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime(); // 非 object 類型的判斷 if (!a || !b || (typeof a !== "object" && typeof b !== "object")) return a === b; if (a.prototype !== b.prototype) return false; if (Array.isArray(a) && Array.isArray(b)) a.sort(), b.sort(); let keys = Object.keys(a); if (keys.length !== Object.keys(b).length) return false; return keys.every(k => equals(a[k], b[k])); };3. mouseover 和 mouseenter 的區(qū)別 ?
mouseover:當(dāng)鼠標(biāo)移入元素或其子元素都會觸發(fā)事件,所以有一個重復(fù)觸發(fā),冒泡的過程。對應(yīng)的移除事件是 mouseout
mouseenter:當(dāng)鼠標(biāo)移除元素本身(不包含元素的子元素)會觸發(fā)事件,也就是不會冒泡,對應(yīng)的移除事件是 mouseleave
4. 一句話形容閉包?閉包就是能夠讀取其他函數(shù)內(nèi)部變量的函數(shù),或者子函數(shù)在外調(diào)用,子函數(shù)所在的父函數(shù)的作用域不會被釋放。
一個閉包小栗子:
function f1(){ n = 999; function f2(){ console.log(n); } return f2; } var result = f1(); //返回的是f2函數(shù) result(); //999,讀取內(nèi)部變量5. js 的 new 操作符做了哪些事情 ?
new 操作符新建了一個空對象,這個對象原型指向構(gòu)造函數(shù)的 prototype,執(zhí)行構(gòu)造函數(shù)后返回這個對象。
6. 實現(xiàn)一個深拷貝 ?//所謂深度克隆,就是當(dāng)對象的某個屬性值為object或array的時候,要獲得一份copy,而不是直接拿到引用值 function deepClone1(origin, target) { //origin是被克隆對象,target是我們獲得copy var target = target || {}; //定義target for (var key in origin) { //遍歷原對象 if (origin.hasOwnProperty(key)) { if (Array.isArray(origin[key])) { //如果是數(shù)組 target[key] = []; deepClone1(origin[key], target[key]); //遞歸 } else if (typeof origin[key] === "object" && origin[key] !== null) { target[key] = {}; deepClone1(origin[key], target[key]); //遞歸 } else { target[key] = origin[key]; } } } return target; } // 第二個function function deepClone2(data) { if (!data || !(data instanceof Object) || typeof data === "function") { return data; } var constructor = data.constructor; var result = new constructor(); for (var key in data) { if (data.hasOwnProperty(key)) { result[key] = deepClone2(data[key]); } } return result; } // 第三個fuction function deepClone3(origin, target) { var target = target || {}, toStr = Object.prototype.toString; for (var prop in origin) { if (origin.hasOwnProperty(prop)) { //不能把原型鏈上的一起拷貝了 //判斷是元素類型還是引用類型 if (typeof origin[prop] == "object" && typeof origin[prop] !== "null") { target[prop] = toStr.call(prop) == "[object Array]" ? [] : {}; arguments.callee(origin[prop], target[prop]); //遞歸調(diào)用 } else { target[prop] = origin[prop]; //原始類型直接復(fù)制 } } } return target; } // 第四個function function deepClone4(obj) { //判斷是否是簡單數(shù)據(jù)類型, if (typeof obj == "object") { //復(fù)雜數(shù)據(jù)類型 var result = obj.constructor == Array ? [] : {}; for (let i in obj) { result[i] = typeof obj[i] == "object" && obj[i] !== null ? deepClone4(obj[i]) : obj[i]; } } else { //簡單數(shù)據(jù)類型 直接 == 賦值 var result = obj; } return result; }
推薦使用 deepClone2()
7. 函數(shù)的防抖與節(jié)流 ?防抖
所謂防抖,就是指觸發(fā)事件后在 n 秒內(nèi)函數(shù)只能執(zhí)行一次,如果在 n 秒內(nèi)又觸發(fā)了事件,則會重新計算函數(shù)執(zhí)行時間。(防誤觸)
// 延緩執(zhí)行 function debounce(func, wait) { var timeout; return function() { var context = this; var args = arguments; console.log(args); console.log(func); if (timeout) clearTimeout(timeout); timeout = setTimeout(function() { func.apply(context, args); }, wait); }; } // 立即執(zhí)行 function debounce(func, wait) { var timeout; return function() { var context = this; var args = arguments; if (timeout) clearTimeout(timeout); var callNow = !timeout; timeout = setTimeout(function() { timeout = null; }, wait); if (callNow) func.apply(context, args); }; }
節(jié)流
所謂節(jié)流,就是指連續(xù)觸發(fā)事件但是在 n 秒中只執(zhí)行一次函數(shù)。(限制流量)
// 時間戳 function throttle(func, wait) { var previous = 0; return function() { var now = Date.now(); var context = this; var args = arguments; if (now - previous > wait) { func.apply(context, args); previous = now; } }; } // 定時器 function throttle(func, wait) { var timeout; return function() { var context = this; var args = arguments; if (!timeout) { timeout = setTimeout(function() { timeout = null; func.apply(context, args); }, wait); } }; }
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/103781.html
摘要:靜態(tài)作用域與動態(tài)作用域靜態(tài)作用域函數(shù)的作用域基于函數(shù)創(chuàng)建的位置。采用的是詞法作用域,也稱為靜態(tài)作用域。可以劫持整個對象,并返回一個新的對象。防誤觸延緩執(zhí)行立即執(zhí)行節(jié)流所謂節(jié)流,就是指連續(xù)觸發(fā)事件但是在秒中只執(zhí)行一次函數(shù)。 在這里記錄著每天自己遇到的一道印象深刻的前端問題,以及一道生活中隨處可見的小問題。 強(qiáng)迫自己形成積累的習(xí)慣,鞭撻自己不斷前行,共同學(xué)習(xí)。 Github 地址 2019...
摘要:問前端的緩存有哪些都適用什么場景區(qū)別是什么參考回答前端緩存分為兩部分緩存瀏覽器緩存緩存強(qiáng)緩存強(qiáng)緩存主要是采用響應(yīng)頭中的和兩個字段進(jìn)行控制的值理解指定設(shè)置緩存最大的有效時間單位為指定響應(yīng)會被緩存,并且在多用戶間共享響應(yīng)只作為私有的緩存, 20190116問: 前端的緩存有哪些?都適用什么場景?區(qū)別是什么? 參考回答 前端緩存分為兩部分: http 緩存 瀏覽器緩存 http 緩存 強(qiáng)...
摘要:問前端的緩存有哪些都適用什么場景區(qū)別是什么參考回答前端緩存分為兩部分緩存瀏覽器緩存緩存強(qiáng)緩存強(qiáng)緩存主要是采用響應(yīng)頭中的和兩個字段進(jìn)行控制的值理解指定設(shè)置緩存最大的有效時間單位為指定響應(yīng)會被緩存,并且在多用戶間共享響應(yīng)只作為私有的緩存, 20190116問: 前端的緩存有哪些?都適用什么場景?區(qū)別是什么? 參考回答 前端緩存分為兩部分: http 緩存 瀏覽器緩存 http 緩存 強(qiáng)...
20190124問: 如何理解es6中的Proxy? 試題解析:對proxy的理解,可能會延伸到vue的雙向綁定 Proxy(代理) 定義 可以理解為為目標(biāo)對象架設(shè)一層攔截,外界對該對象的訪問,都必須通過這層攔截 簡單示例: const obj = new Proxy({}, { get: (target, key, receiver) => { return JS ...
閱讀 1332·2021-11-15 18:14
閱讀 3306·2021-08-25 09:38
閱讀 2739·2019-08-30 10:55
閱讀 2795·2019-08-29 16:39
閱讀 1372·2019-08-29 15:07
閱讀 2506·2019-08-29 14:14
閱讀 877·2019-08-29 12:36
閱讀 975·2019-08-29 11:21