滴滴 就记住这几个。
react-router 动态路由
Webpack 中的 loader 和 plugin 区别 Loader 的作用是让 webpack 拥有加载和解析非 JavaScript 文件的能力。Plugin 是扩展 Webpack 的功能,在 webpack 运行的生命周期中。
Chunk 和 bundle 的区别 chunk 是打包过程中的文件,bundle 是打包的结果。
Webpack 的构建优化 可以看我另外一篇写的构建优化
Hook:useEffect useRef useCallback useMemo 解释了一下用法,原理。什么时候用。
描述 Redux 数据流 单项数据流:dispatch(Action)->Reducer->Store.
React-sugar 用过吗? 没用过。
React 是如何数据驱动视图的 看卡颂大佬的 React 源码解析 。
Node 的事件循环(10 为分界线) 看我摘抄淘宝前端团队的那篇文章《JavaScript 之事件循环》
强缓存协商缓存
强缓存:cache- control 和 expiress 协商缓存:last-modify 和 If-Modified-Since:和时间有关,时间不一致会有问题。Etag 和 If-None-Match:服务端先对文件生成唯一标识 ETag,在第一次请求的时候带回来,第二次请求的时候请求头会有 If-None-Match:ETag 值的形式,如果 ETag 不匹配就拿新资源,匹配就返回 304。 怎么判断啥时候该去请求最新的资源,啥时候去请求 service Worker 这个没回答,因为不了解 ServiceWorker,然后跟面试官讲了一下我所知道的 serviceWorker,PWA 以及用 serviceWorker 实现的 mock 方案这些。 具体可以看service Worker 第十点的缓存管理,大概就是在 servicerWoker 的 install 阶段时,open 待版本号的 cache,版本号变了就会更新了。
实现深拷贝 当时没实现出来,哈哈哈哈哈,只是面试官说了一下递归,遇到 object 就下一层这样的一个思路。因为但是只记得处理 Object
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 function deepClone (value, hashMap = new WeakMap () ) { if (value == undefined || typeof value !== 'object' ) { return value; } if (value instanceof Date ) { return new Date (value); } if (value instanceof RegExp ) { return new RegExp (value); } const hashKey = hashMap.get(value); if (hashKey) { return hashKey; } const result = new value.constructor(); hashMap.set(value, result); Object .keys(value).forEach((key ) => { result[key] = deepClone(value[key], hashMap); }) return result; }
数组去重 哈哈哈哈哈,这个我也没实现。我比较皮的说了一句 Array.from(new Set())
,然后面试官说不行。 然后我就搞了个 Map,遍历全部全部元素,key 就是 array[i]。然后面试官问我这种方式遇到undefined
怎么办,我说undefined
是可以作为 key 的,之前手滑给过一次 undefined,然后引发了 bug 哈哈哈哈,然后又问我能不能存[1,2,3,[4,5]]
的第三项,我当时不太确定能不能存,告诉面试官不确定。 function arrayNonRepeatfy (arr ) { let map = new Map (); let array = new Array (); for (let i = 0 ; i < arr.length; i++) { if (map.has(arr[i])) { map.set(arr[i], i); } else { map.set(arr[i], i); array.push(arr[i]); } } return array ; }
不过这种不能应对[1,2,3,[4,5],5,[4,5]]
去重。可以判断一下是Array.isArray(num)||(typeof num === "object" && num !== null)
,然后用 JSON.stringify 一下再存到 Map 里,在 has 判断的时候也先序列化一下。
实现一个 moment.format 这个当时也没实现,也是仅仅实现了个不传 paramDate 和 formatStr 的最简单版本,只是跟面试官说了一下要想实现传入 formatStr 的这个,用正则会方便点。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 const format = (paramDate, formatStr ) => { const date = new Date (paramDate) || new Date (); const year = date.getFullYear(); const month = date.getMonth() + 1 ; const day = date.getDate(); const week = date.getDay(); const hour = date.getHours(); const minute = date.getMinutes(); const second = date.getSeconds(); return formatStr ? formatStr.replace( /Y{2,4}|M{1,2}|D{1,2}|d{1,4}|H{1,2}|m{1,2}|s{1,2}/g , (match ) => { switch (match) { case "YY" : return String (year).slice(-2 ); case "YYY" : case "YYYY" : return String (year); case "M" : return String (month); case "MM" : return String (month).padStart(2 , "0" ); case "D" : return String (day); case "DD" : return String (day).padStart(2 , "0" ); case "d" : return String (week); case "dd" : return weeks[week]; case "ddd" : return "周" + weeks[week]; case "dddd" : return "星期" + weeks[week]; case "H" : return String (hour); case "HH" : return String (hour).padStart(2 , "0" ); case "m" : return String (minute); case "mm" : return String (minute).padStart(2 , "0" ); case "s" : return String (second); case "ss" : return String (second).padStart(2 , "0" ); default : return match; } } ) : `${year} -${month} -${day} ${hour} :${minute} :${second} ` ; };
实现一个符合 promise/A+的 promise。
看我前段时间写的手撕 promise
看代码题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 async function async1 ( ) { console .log("async1 start" ); await async2(); console .log("async1 end" ); }async function async2 ( ) { new Promise (function (resolve ) { console .log("promise1" ); resolve(); }).then(function ( ) { console .log("promise2" ); }); }console .log("script start" );setTimeout (function ( ) { console .log("setTimeout" ); }, 0 ); async1();new Promise (function (resolve ) { console .log("promise3" ); resolve(); }).then(function ( ) { console .log("promise4" ); });console .log("script end" );
实现一个 sleep 函数,多种方式,比如 sleep(1000) 阻塞 js 执行就可以
const sleep = (num, fn ) => { let start = new Date ().getTime(); while (new Date ().getTime() - start < num); fn(); };const sleep = (num ) => { return new Promise ((resolve ) => { setTimeout (() => { resolve(); }, num); }); };
合并两个有序整数数组,使之成为一个有序数组,function(arr, brr) ,假设 arr 长度刚好容纳所有数据 var merge = function (nums1, nums2 ) { let nums1First = nums1.length - nums2.length - 1 , nums1Second = nums1.length - 1 , nums2First = nums2.length - 1 ; while (nums1First >= 0 && nums2First >= 0 ) { nums1[nums1Second--] = nums1[nums1First] > nums2[nums2First] ? nums1[nums1First--] : nums2[nums2First--]; } nums1.splice(0 , nums2First + 1 , ...nums2.slice(0 , nums2First + 1 )); return nums1; };
美团打车 实现 checkbox 组件,提供给其他人使用 看代码题 var name = "张三" ;const people = { name : "李四" , sayName ( ) { console .log(this .name); }, }; people.sayName();const temp = people.sayName; temp();
给定一个数组,移除所有相邻相同数字,直到没有相邻相同数字为止。 Input: [1, 2, 3, 3, 4, 4, 2, 5, 7, 7, 5, 6, 8, 1] Output: [1, 6, 8, 1]
const filter = (arr ) => { const res = []; arr.forEach((item ) => { if (res[res.length - 1 ] === item) { res.pop(); } else { res.push(item); } }); return res; };
hash contentHash chunkHash 区别 hash:工程级别,修改任何一个文件都会导致所有文件 hash 改变
chunkHash:模块级别的,根据不同的入口文件(Entry)进行依赖文件解析、构建对应的 chunk,生成对应的哈希值。
contentHash:文件内容级别的,内容不同产生的 hash 就不同。