-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
常见前端面试题 #6
Comments
前端内容
|
eventloop 的理解, 我的博客Q1: setTimeout(function() {
setTimeout(function() { console.log(1) }, 100)
console.log(2)
setTimeout(function() { console.log(3) }, 0)
}, 0)
setTimeout(function () {
console.log(4)
}, 100)
console.log(5)
// 输出顺序: 5 2 3 4 1 Q2: console.log('script start')
let promise1 = new Promise(function (resolve) {
console.log('promise1')
resolve()
console.log('promise1 end')
}).then(function () {
console.log('promise2')
})
setTimeout(function(){
console.log('settimeout')
})
console.log('script end')
// 输出顺序: script start->promise1->promise1 end->script end->promise2->settimeout Q3: async function async1(){
console.log('async1 start');
await async2();
console.log('async1 end')
}
async function async2(){
console.log('async2')
}
console.log('script start');
async1();
console.log('script end')
// 输出顺序:script start->async1 start->async2->script end->async1 end Q4: function* generator(i) {
console.log('inside before')
yield i;
yield i + 10;
console.log('inside after')
}
var gen = generator(10);
console.log('outside before')
console.log(gen.next().value);
console.log(gen.next().value);
console.log('outside after')
gen.next();
/**
* outside before
* inside before
* 10
* 20
* outside after
* inside after // 如果不加最后一个gen.next(); 就不会有这一行
*/ |
Q: 完成一个 sum 函数,使调用后输出 6
sum(1)(2)(3).valueOf() function curryingHelper(fn, ...args) {
return (...newArgs) => {
return fn.apply(this, args.concat(newArgs));
}
}
// fn.length:获取 fn 的参数个数
function betterCurryingHelper(fn, length = fn.length) {
return (...args) => {
let allArgsFulfilled = args.length >= length
// 如果参数全部满足,就可以终止递归调用
if (allArgsFulfilled) {
return fn.apply(this, args);
} else {
let argsNeedFulfilled = [fn].concat(args);
return betterCurryingHelper(curryingHelper.apply(this, argsNeedFulfilled), length - args.length)
}
}
}
function add(a, b, c) {
return {
valueOf() {
return a + b + c
}
}
}
var sum = betterCurryingHelper(add)
sum(1)(2)(3).valueOf() |
|
改造下面的代码,使之输出0 - 9,写出你能想到的所有解法。 for (var i = 0; i< 10; i++){
setTimeout(() => {
console.log(i);
}, 1000)
} 解: // 解一
for (var i = 0; i< 10; i++){
setTimeout((i) => {
console.log(i);
}, 1000, i)
}
// 解二
for (let i = 0; i< 10; i++){
setTimeout(() => {
console.log(i);
}, 1000)
}
// 解三
for (var i = 0; i< 10; i++){
setTimeout((function(i) {
console.log(i);
})(i), 1000)
} |
下面的代码打印什么内容,为什么?
var b = 10;
(function b(){
b = 20;
console.log(b);
})();
/**
ƒ b() {
b = 20;
console.log(b)
}
*/
|
下面代码中 a 在什么情况下会打印 1? var a = ?;
if(a == 1 && a == 2 && a == 3){
conso.log(1);
}
var a = {
i: 1,
toString() {
return a.i++;
}
}
if( a == 1 && a == 2 && a == 3 ) {
console.log(1);
} var a = {
i: 1,
valueOf() {
return a.i++;
}
}
if( a == 1 && a == 2 && a == 3 ) {
console.log(1);
} |
[3, 15, 8, 29, 102, 22].sort()
// [102, 15, 22, 29, 3, 8]
[3, 15, 8, 29, 102, 22].sort((a, b) => a - b)
// [3, 8, 15, 22, 29, 102] |
实现 (5).add(3).minus(2) 功能,参考 Daily-Interview-Question#88 简易版 Number.prototype.add = function(n) {
return this.valueOf() + n;
};
Number.prototype.minus = function(n) {
return this.valueOf() - n;
}; 完整版 Number.MAX_SAFE_DIGITS = Number.MAX_SAFE_INTEGER.toString().length-2
Number.prototype.digits = function(){
let result = (this.valueOf().toString().split('.')[1] || '').length
return result > Number.MAX_SAFE_DIGITS ? Number.MAX_SAFE_DIGITS : result
}
Number.prototype.add = function(i=0){
if (typeof i !== 'number') {
throw new Error('请输入正确的数字');
}
const v = this.valueOf();
const thisDigits = this.digits();
const iDigits = i.digits();
const baseNum = Math.pow(10, Math.max(thisDigits, iDigits));
const result = (v * baseNum + i * baseNum) / baseNum;
if(result>0){ return result > Number.MAX_SAFE_INTEGER ? Number.MAX_SAFE_INTEGER : result }
else{ return result < Number.MIN_SAFE_INTEGER ? Number.MIN_SAFE_INTEGER : result }
}
Number.prototype.minus = function(i=0){
if (typeof i !== 'number') {
throw new Error('请输入正确的数字');
}
const v = this.valueOf();
const thisDigits = this.digits();
const iDigits = i.digits();
const baseNum = Math.pow(10, Math.max(thisDigits, iDigits));
const result = (v * baseNum - i * baseNum) / baseNum;
if(result>0){ return result > Number.MAX_SAFE_INTEGER ? Number.MAX_SAFE_INTEGER : result }
else{ return result < Number.MIN_SAFE_INTEGER ? Number.MIN_SAFE_INTEGER : result }
} |
阅读链接: 缓存缓存对于前端性能优化来说是个很重要的点,良好的缓存策略可以降低资源的重复加载提高网页的整体加载速度。 通常浏览器缓存策略分为两种:强缓存和协商缓存。 强缓存实现强缓存可以通过两种响应头实现:
协商缓存如果缓存过期了,我们就可以使用协商缓存来解决问题。协商缓存需要请求,如果缓存有效会返回 304。 |
算法 1.快排 function quickSort(arr){
//如果数组<=1,则直接返回
if(arr.length<=1){return arr;}
var pivotIndex=Math.floor(arr.length/2);
//找基准,并把基准从原数组删除
var pivot=arr.splice(pivotIndex,1)[0];
//定义左右数组
var left=[];
var right=[];
//比基准小的放在left,比基准大的放在right
for(var i=0;i<arr.length;i++){
if(arr[i]<=pivot){
left.push(arr[i]);
}
else{
right.push(arr[i]);
}
}
//递归
return quickSort(left).concat([pivot],quickSort(right));
} 2.给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序 示例: 输入: [0,1,0,3,12]
输出: [1,3,12,0,0] 说明:
Answer: 思路:双指针 设定一个慢指针一个快指针,快指针每次+1, 当慢指针的值不等于0的时候也往后移动,当慢指针等于0并且快指针不等于0的时候,交换快慢指针的值,慢指针再+1 function moveZero(arr) {
let i = 0
let j = 0
while (j < arr.length) {
if (arr[i] !== 0) {
i++
} else if (arr[j] !== 0) {
;[arr[i], arr[j]] = [arr[j], arr[i]]
i++
}
j++
}
} 时间复杂度O(n),n是数组长度,空间复杂度O(1) |
var arr1 = [1, 2, [3, 4]];
arr1.flat();
// 反嵌套一层数组
arr1.reduce((acc, val) => acc.concat(val), []);// [1, 2, 3, 4]
// 或使用 ...
const flatSingle = arr => [].concat(...arr);
// 使用 reduce、concat 和递归无限反嵌套多层嵌套的数组
var arr1 = [1,2,3,[1,2,3,4, [2,3,4]]];
function flattenDeep(arr1) {
return arr1.reduce((acc, val) => Array.isArray(val) ? acc.concat(flattenDeep(val)) : acc.concat(val), []);
}
flattenDeep(arr1);
// [1, 2, 3, 1, 2, 3, 4, 2, 3, 4] 参考 MDN:Array 的一些用法: 修改 var fruits = [];
fruits.push('banana', 'apple', 'peach');
fruits[5] = 'mango'; // 给超出当前数组大小的下标赋值
console.log(Object.keys(fruits)); // ['0', '1', '2', '5']
console.log(fruits.length); // 6
console.log(fruits); // ["banana", "apple", "peach", empty × 2, "mango"]
fruits.length = 2; // 为 length 赋一个更小的值则会删掉一部分元素
console.log(Object.keys(fruits)); // ['0', '1']
console.log(fruits.length); // 2
Array.from('foo') // ["f", "o", "o"]
function f() {
return Array.from(arguments);
}
f(1, 2, 3); // [1, 2, 3]
Array.from({length: 5}, (v, i) => i); // [0, 1, 2, 3, 4]
Array.from({length: 5}, () => 6); // [6, 6, 6, 6, 6]
Array(5).fill(6); // [6, 6, 6, 6, 6]
Array(5).join('6').split(''); // ["6", "6", "6", "6"]
// !Objects by reference.
var arr = Array.from({length: 3}).fill({}) // [{}, {}, {}];
arr[0].hi = "hi"; // [{ hi: "hi" }, { hi: "hi" }, { hi: "hi" }]
// !Objects by reference.
var arr = Array(3).fill([]) // [[], [], []];
arr[0].push("hi"); // [["hi"], ["hi"], ["hi"]]
// es6
Array.from({length: 3}, () => {}) // [undefined, undefined, undefined]
Array.from({length: 3}, () => ({})) // [{}, {}, {}]
Array.from({length: 3}, () => [])) // [[], [], []]; Q: 求两个数组的交集并集? 测试用例: var nums1 = [1], nums2 = [1,1];
var nums1 = [1, 2, 2, 1], nums2 = [2, 2];
var nums1 = [1, 2, 2, 1], nums2 = [2, 2, 1]; // 交集
const intersect = (nums1, nums2) => {
const map = {}
const res = []
for (let n of nums1) {
if (map[n]) {
map[n]++
} else {
map[n] = 1
}
}
for (let n of nums2) {
if (map[n] > 0) {
res.push(n)
map[n]--
}
}
return res
} // 并集
const union = (nums1, nums2) => Array.from(new Set(nums1.concat(nums2)))
const union = (nums1, nums2) =>nums1.concat(nums2).reduce((acc, val, index) => acc.includes(val) ? acc : acc.concat(val), []) |
javascript 判断一个数字是否为质数 function isPrime(element) {
var start = 2;
while (start <= Math.sqrt(element)) {
if (element % start++ < 1) {
return false;
}
}
return element > 1;
} 正则表达式(待验证) function isPrimeNum2(num){
return !/^.?$|^(..+?)\1+$/.test(Array(num + 1).join('1'))
} |
100 元的红包分给 10 个人抢,每个人最少 6 元,最多 12 元,求怎么分配? function sharing(total, count, max, min = 0) {
var array = Array(count).fill(min)
var left = total - count * min
var once
var index
while (left > 0) {
once = Math.floor(Math.random() * (max - min))
index = Math.floor(Math.random() * (count - 1))
if (array[index] + once <= max) {
array[index] += once
left -= once
}
}
return array
}
var x = sharing(100, 10, 12, 6)
console.log(x) // [12, 10, 10, 11, 11, 9, 10, 12, 9, 6] |
Fibonacci 实现方式 递归非常耗费内存,因为需要同时保存成千上百个调用帧,很容易发生“栈溢出”错误(stack overflow)。 function Fibonacci (n) {
if ( n <= 1 ) {return 1};
return Fibonacci(n - 1) + Fibonacci(n - 2);
} 但对于尾递归来说,由于只存在一个调用帧,所以永远不会发生“栈溢出”错误。 function Fibonacci2 (n , ac1 = 1 , ac2 = 1) {
if( n <= 1 ) {return ac2};
return Fibonacci2 (n - 1, ac2, ac1 + ac2);
} 迭代版本:(n = 10e6, time: 66.8ms) function iterFib(n) {
let last = 1;
let nextLast = 1;
let result = 1;
for (let i = 2; i < n; ++i) {
result = last + nextLast;
nextLast = last;
last = result;
}
return result;
} 动态规划:(n = 10e6, time: 410.4ms) function dynFib(n) {
let val = [];
for (let i = 0; i <= n; ++i) {
val[i] = 0;
}
if (n === 1 || n === 2) {
return 1;
} else {
val[1] = 1;
val[2] = 2;
for (let i = 3; i <= n; ++i) {
val[i] = val[i - 1] + val[i - 2];
}
}
return val[n - 1]
} perffunction main(fn, x){
console.time('t')
fn(x)
console.timeEnd('t')
}
main(Fibonacci2, 400) // t: 0.02099609375 ms
main(iterFib, 400) // t: 0.010009765625 ms
main(dynFib, 400) // t: 0.097900390625 ms |
Vue 相关
proxy reactive 实现 |
基础问题:
new 适用于使用构造函数创建对象并继承原型链的场景,而 Object.create 适用于直接创建对象并继承指定对象的属性和方法的场景。根据具体的需求和场景,选择合适的创建方式。
Object.create(null) 创建的对象没有原型链,不继承任何属性和方法。 |
es6 新增语法有哪些 |
手写 promise (async、await、generator、Iterator) |
事件循环:async/await、setTimeout、nextTick、promise 的执行顺序 |
sleep 函数: function sleepSync(delay) {
let endTime = new Date().getTime() + parseInt(delay);
while (new Date().getTime() < endTime);
}
function sleepAsync(delay) {
return new Promise((resolve) => setTimeout(resolve, delay));
} |
面试过程中,需要回答和提问的问题(参考 tech-interview-handbook)
面试题:
The text was updated successfully, but these errors were encountered: