面试题
事件循环,执行顺序
setTimeout(() => {
console.log('111');
})
new Promise((resolve) => {
console.log('222');
setTimeout(() => {
resolve()
}, 3000)
}).then(() => {
console.log('333');
})
console.log('444');
// 2 4 1 3
当然最开始顺序执行主线程程序,会log出one、four。这里又涉及到异步的宏任务和微任务,setTimeout加入macrotask队列,是宏任务,Promise加入microtask队列,整体是微任务,主线程执行完了之后先从微任务栈里面获取微任务执行,没有微任务了,就去宏任务栈里面获取宏任务执行,所以在一个循环内,微任务是比宏任务先执行的
对象转数组
{a:1, b:2, c:3} 转成[{a:1}, {b:2}, {c:3}]
function objToArr(obj) {
const arr = [];
const Obj = {};
for (const key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
Obj[key] = obj[key];
}
}
arr.push(Obj);
return arr;
}
继承方式
https://github.com/mqyqingfen...
2 对象数组排序
var presonArr = [
{ name:'freddy', age:24, score:97 },
{ name:'nick', age:18, score:87 },
{ name:'mike', age:26, score:80 },
{ name:'james', age:34, score:90 },
{ name:'curry', age:30, score:83 }
];
//年龄升序排序
presonArr.sort(function(a,b){
return a.age - b.age;
});
console.log(presonArr);
数组引用值,深拷贝
var arr1 =[{a:1}, {b:2}, 3]
var arr2 = [].concat(arr1); // arr2 = [...arr1];
arr1 === arr2; // ?
arr1[0] === arr2[0] // ?
arr1[2] === arr2[2] // ?
arr1[0].a = 666;
arr2[0].a = ?
arr1[2] = 888;
arr2[2] = ?
继续问深拷贝
function deepCopy(data: any, hash = new WeakMap()) {
if (typeof data !== 'object' || data === null) {
throw new TypeError('传入参数不是对象');
}
// 判断传入的待拷贝对象的引用是否存在于hash中
if (hash.has(data)) {
return hash.get(data);
}
const newData = {};
const dataKeys = Object.keys(data);
dataKeys.forEach(value => {
const currentDataValue = data[value];
// 基本数据类型的值和函数直接赋值拷贝
if (typeof currentDataValue !== 'object' || currentDataValue === null) {
newData[value] = currentDataValue;
}
else if (Array.isArray(currentDataValue)) {
// 实现数组的深拷贝
newData[value] = [...currentDataValue];
}
else if (currentDataValue instanceof Set) {
// 实现set数据的深拷贝
newData[value] = new Set([...currentDataValue]);
}
else if (currentDataValue instanceof Map) {
// 实现map数据的深拷贝
newData[value] = new Map([...currentDataValue]);
}
else {
// 将这个待拷贝对象的引用存于hash中
hash.set(data, data);
// 普通对象则递归赋值
newData[value] = deepCopy(currentDataValue, hash);
}
});
return newData;
}
展开多维数组
// 写出一个数组展开函数, 如输入:[1,[2,[3,4,2],2],5,[6]], 则输出:[1,2,3,4,2,2,5,6]
// 因为和深度无关,所以说最简单可以这样
function flatten(arr){ var res = arr.join().split(',');
res = res.map( ele => +ele) return res;
} // 还有吗,递归,写一下
function flatten(arr){ var array = [];
arr.forEach(ele => { if(Array.isArray(ele)){
array.push(...flatten(ele));
} else {
array.push(ele);
}
}) return array;
}
实现Promise.all
// 1.实现Promise.all()
https://segmentfault.com/a/11...
Promise.myAll = function(iterators) {
const promises = Array.from(iterators);
const num = promises.length;
const resolvedList = new Array(num);
let resolvedNum = 0;
return new Promise((resolve, reject) => {
promises.forEach((promise, index) => {
Promise.resolve(promise)
.then(value => {
// 保存这个promise实例的value
resolvedList[index] = value;
// 通过计数器,标记是否所有实例均 fulfilled
if (++resolvedNum === num) {
resolve(resolvedList);
}
})
.catch(reject);
});
});
};
6 reduce及reduce数组去重
5、Array.reduce() -- 不改变原数组
reduce(function(pre,cur,index,array){}, initValue)
pre相当于一个容器,存放每次执行的结果;每次return的值会作为下次的pre。
回调函数第一次执行时,previousValue
和 currentValue
可以是一个值,如果 initialValue 在调用 reduce 时被提供,那么第一个 previousValue 等于 initialValue ,并且currentValue 等于数组中的第一个值;如果initialValue 未被提供,那么previousValue 等于数组中的第一个值,currentValue等于数组中的第二个值。
var arr = [1,2,3,4];
arr.reduce(function(previousValue, currentValue){
return previousValue * currentValue;
}); // 24
console.log(arr); // [1,2,3,4]
// 数组去重
var arr = [1,2,3,2,3,4];
var newarr = arr.reduce(function(acc, cur){
!acc.includes(cur) && acc.push(cur);
return acc;
},[]);
console.log(newArr); // [1,2,3,4]
手写useState
let _state=[];
let index=0;
function myUseState(initialValue) {
int currentIndex=index; //引入中间变量currentIndex就是为了保存当前操作的下标index。
_state[currentIndex] = _state[currentIndex]===undefined? initialValue:_state[currentIndex];
const setState = (newValue) => {
_state[currentIndex] = newValue;
render();
};
index+=1;// 每次更新完state值后,index值+1
return [_state[currentIndex], setState];
}
const render = () => {
index=0; //重要的一步,必须在渲染前后将index值重置为0,不然index会一种增加1
ReactDOM.render( , document.getElementById("root"));
};
写一个快排 排序
var quickSort = function(arr) {
if (arr.length <= 1) { return arr; }
var pivotIndex = Math.floor(arr.length / 2);
var pivot = arr.splice(pivotIndex, 1)[0];
var left = [];
var 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));
};
找出字符串中最长的回文字串-动态规划
动态规划的精髓是局部最优全局最优
function getResult(s) {
if (!s || s.length === 1) return s;
const len = s.length;
let res = s[0];
for (let i = 0; i < len; i++) {
let j = 1;
let tmpStr1 = '';
let tmpStr2 = '';
if (s[i] === s[i + 1] && s[i + 1]) {
const doubleStr = `${s[i]}${s[i + 1]}`;
res = res.length > doubleStr.length ? res : doubleStr;
}
tmpStr1 = s[i];
// 判断 ada 类型(奇数长度)回文
while (s[i - j] === s[i + j] && s[i - j] && s[i + j]) {
tmpStr1 = s[i - j] + tmpStr1 + s[i + j];
j++;
}
// 判断 aaaa 类型(偶数长度)回文
j = 1;
while (s[i - j] === s[i + j - 1] && s[i - j] && s[i + j - 1]) {
tmpStr2 = s[i - j] + tmpStr2 + s[i + j - 1];
j++;
}
const tmpStr = tmpStr1.length > tmpStr2.length ? tmpStr1 : tmpStr2;
res = res.length > tmpStr.length ? res : tmpStr;
}
return res;
}
最长不重复子串
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。