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