面试题

事件循环,执行顺序

 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(<App />, 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。


张长长
67 声望4 粉丝