怎么学习前端的
CSS position 你知道哪些有哪些属性
感谢总结的面经,我成功答了出来这个
值 | 描述 |
---|---|
absolute | 生成绝对定位的元素,相对于 static 定位以外的第一个父元素进行定位。元素的位置通过 "left", "top", "right" 以及 "bottom" 属性进行规定。 |
fixed | 生成绝对定位的元素,相对于浏览器窗口进行定位。元素的位置通过 "left", "top", "right" 以及 "bottom" 属性进行规定。 |
relative | 生成相对定位的元素,相对于其正常位置进行定位。因此,"left:20" 会向元素的 LEFT 位置添加 20 像素。 |
static | 默认值。没有定位,元素出现在正常的流中(忽略 top, bottom, left, right 或者 z-index 声明)。 |
inherit | 规定应该从父元素继承 position 属性的值。 |
追问:被问如果父元素没有设置position:relative,子节点设置position:absolute怎么办,找到position:static以外的第一个父元素。(嘻嘻,总结过)
再被追问如果所有父元素都是position:static,怎么办,相对body还是窗口?这又是盲区了
查了W3C,总体说对了,相对于body定位,并随页面滚动一起移动。
HTTP缓存
强制缓存协商缓存,经典问题
追问:协商缓存的校验是在客户端还是服务器端?
想了想客户端?
提示我:你怎么知道要应用协商缓存?
304状态码
状态码是谁提供的?
服务器端,所以刚刚说错了,协商缓存的校验是在服务器端
那强制缓存是在客户端还是服务器端?
客户端,因为根本没有向服务器端发送请求
好好,手写一道题吧
fs.readFile('1.txt', (err, data) => { }); const newReadFile = promisify(fs.readFile); newReadFile('1.txt') .then(data => {}) .catch(err => {}); 手写promisify函数
我一看不会,还没看过,硬着头皮写吧
function promisify(fn) { return Promise() }刚写,面试官提示我,返回的是一个什么,想了想,应该是function。自己琢磨了很久,写了这些代码,一边写,一边说自己的思路,但还是写错了
function promisify(fn) { let data, err return function(...args) { try { data = fn(...args); }.catch { err } } }
提示我为什么要用promisify,自己写不下去了,自己在这里反思一下promisify的做法。
首先 promisify 需要返回一个 function
function promisify(fn) { return function() { } }
并且这个 function 要返回一个 promise,Promise中调用传入的函数
function promisify(fn) { return function(...args) { return new Promise(function(resolve) { fn(...args); }) } }
原fn函数的最后一个参数是 callback,实现回调
function promisify(fn) { return function(...args) { return new Promise(function(resolve) { args.push(function(result) { resolve(result); }) fn(...args); }) } }
考虑回调函数中的第一个参数是 error 标记
function promisify(fn) { return function(...args) { return new Promise(function(resolve, reject) { args.push(function(error, result) { if (error) reject(error); else resolve(result); }) fn(...args); }) } }
参考了网上的资料,总算手写了出来,值得好好品味
面试官看我写不出来,然后给我换了道简单的题,说是类似的原理,要求f,其实sleep函数我知道怎么写
setTimeout(() => console.log('hi'), 500); const sleep = f(setTimeout); sleep(500).then(() => consle.log('hi'));可是这个f我依然一筹莫展,最后当场写出来的是这个玩意,实在很抱歉
function f(fn) { return function(...args) { return Promise( fn(args[1]); ).then( args[0]; ) } }
按照复盘的思路,重写一个吧
function f(fn) { return function(...args) { return new Promise(function(resolve) { args.unshift(resolve); fn(...args); }) } }
顺带整理一下sleep函数的写法
1.使用Promise
function sleep(time) { return new Promise(function(resolve) { setTimeout(resolve, time); }) } // 使用 sleep(1000).then(() => { console.log(1); })
2.使用生成器Generator
function* sleepGenerator(time) { yield new Promise(function(resolve, reject) { setTimeout(resolve, time); }) } // 使用 sleepGenerator(1000).next().value.then(() => { console.log(1); })
3.使用async、await
function sleep(time) { return new Promise(resolve => { setTimeout(resolve, time); }) } async function output(time) { let out = await sleep(time); console.log(1); return out; } output(1000);
4.ES5
function sleep(callback, time) { if (typeof(callback) === 'function') { setTimeout(callback, time); } } function output() { console.log(1); } sleep(output, 1000);
手写flat([1, [2, [3, [4]]]]) -> [1, 2, 3, 4]函数
机智如我先说了arr自带的flat方法
function flat(arr) { return arr.flatten(Infinity); }
我又写错了,正确的应该是
function flat(arr) { return arr.flat(Infinity); }
面试官说就是要实现它,不要用自带的flat函数
我说可以用正则表达式,然后手写了
function flat(arr) { return arr.toString().replace(/[|]/g, '').split(','); }面试官提醒,正则表达式中[和]有什么作用
赶紧解释[]表示匹配中间对应的字符,用转义符才能实现匹配
function flat(arr) { return arr.toString().replace(/\[|\]/g, '').split(','); }
面试官又说如果本身里面带字符串,字符串中有,就无法实现
我终于决定使用递归的方案做了一版
function flat(arr) { let res = []; for (let item of arr) { if (item.constructor == Array) { // if (instanceof(item) == Array) { res.push(...flat(item)); } else { res.push(item); } } return res; }
其中我还写了一下判断数组的方法
Array.isArray(arr); instanceof(arr) == Array arr.constructor == Array; // 没来及写的 Object.prototype.toString.call(arr) === '[object Array]';
面试官又说这样数组有什么情况(我记不得了)这种方法不管用
查了查有可能的情况,发现是数组空位,ES5 大多数数组方法对空位的处理都会选择跳过空位包括:forEach(), filter(), reduce(), every() 和 some() 都会跳过空位。
使用reduce实现
function flat(arr) { return arr.reduce((pre, cur) => { return pre.concat(Array.isArray(cur) ? flat(cur) : cur); }, []); }
使用forEach实现
function flat(arr) { let res = []; arr.forEach(function (item){ if (item.constructor == Array) { // if (instanceof(item) == Array) { res.push(...flat(item)); } else { res.push(item); } }) return res; }
手写trim,用最笨的方法
\s
function trim(str) { let arr = str.split(''); let i = 0; while (arr[i] === ' ') { arr.shift(); } i = arr.length - 1; while (arr[i] === ' ') { arr.pop(); i--; } return arr.join(''); }
说了正则表达式
function trim(str) { return str.replace(/^[\s]+/, '').replace(/[\s]+$/, ''); }
想了想说可以合并
没写,说是利用g后缀
function trim(str) { return str.replace(/(^[\s]+)|([\s]+$)/g, ''); }
反问:
全部评论
(11) 回帖