头条面试题

255 阅读2分钟

1、定时输出0,1,2

题目: 修改以下代码,使定时器依次输出0,1,2

for (var i = 0; i < 3; i++) {
  console.log('gsy--0', new Date().getTime(),i)
  setTimeout(() => {
    console.log('gsy---1', new Date().getTime(),i) 
  }, 1000);
}

for (let i = 0; i < 3; i++) {
  console.log('gsy--0', new Date().getTime(),i)
  setTimeout(() => {
    console.log('gsy---1', new Date().getTime(),i) 
  }, 1000);
}

for (let i = 0; i < 3; i++) {
  console.log('gsy--0', new Date().getTime(),i)
  setTimeout(() => {
    console.log('gsy---1', new Date().getTime(),i) 
  }, i*1000);
}

可参考

2、任务队列---事件池

new Queue()
.task(1000,()=>console.log(1))
.task(2000,()=>console.log(2))
.task(3000,()=>console.log(3))
.start()
实现该函数,start()后等1秒输出1,再等2秒输出2,再等3秒输出3.
  • promise的then的链式调用
  • 链式调用返回this

Class写法

class Queue {
  constructor() {
    console.log('gsy---constructor', new Date().getTime())
    this.queue = []
  }
  task(times, cb) {
    this.queue.push({
      times,
      cb
    })
    console.log('gsy---task', this.queue)
    return this
  }
  async start() {
    let result = Promise.resolve()
    while (this.queue.length > 0) {
      const {
        times,
        cb
      } = this.queue.shift()

      result = result.then(() => {
        console.log('gsy---then', new Date().getTime())
        return new Promise((resolve) => {
          setTimeout(() => {
            cb();
            console.log('gsy---resolve', new Date().getTime())
            resolve()
          }, times)
        })
      })
      console.log('gsy---result', new Date().getTime())
    }
  }
}

new Queue()
  .task(1000, () => {
    console.log(1)
  })
  .task(2000, () => {
    console.log(2)
  })
  .task(3000, () => {
    console.log(3)
  })
  .start()

ES5

function Quene() {
  this.quene = [];
}

Quene.prototype.task = function (time, callback) {
  this.quene.push({
    time,
    callback
  });
  return this;
};

Quene.prototype.start = function () {
  const quene = this.quene;
  let result = Promise.resolve();
  quene.forEach((item) => {
    result = result.then(() => {
      console.log('gsy---then', new Date().getTime())
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve(item.callback());
          console.log('gsy---resolve', new Date().getTime())
        }, item.time);
      });
    });
    console.log('gsy---result', result)
  });

  return result;
};


new Quene()
  .task(1000, () => {
    console.log(1)
  })
  .task(2000, () => {
    console.log(2)
  })
  .task(3000, () => {
    console.log(3)
  })
  .start()
  • async await时间叠加(不建议)
async function one() {
  console.log('gsy---0', new Date().getTime())
  setTimeout(function () {
    console.log(1);
    console.log('gsy---setTimeout', new Date().getTime())
    }, 1000);
}
async function two() {
  console.log('gsy---0', new Date().getTime())
  setTimeout(await
    function () {
      console.log(2);
      console.log('gsy---setTimeout', new Date().getTime())
    }, 3000);
}
async function three() {
  console.log('gsy---0', new Date().getTime())
  setTimeout(await
    function () {
      console.log(3);
      console.log('gsy---setTimeout', new Date().getTime())
    }, 4000);
}
async function run() {
  var p1 = await one();
  var p2 = await two();
  var p3 = await three();
}
run();

3、原型链以及this

  • window.name 赋值 window.name,这是一个window默认自带的属性,类型为“string”,不可改变其类型,也就是说,如果对其赋值,值必须为string类型,否则会自动调用值的toString方法,将值转换为string类型。
  • 函数体
  • call
//  输出为string
typeof window.name
//  更改其类型为number
window.name = 100
//  依旧输出为string
typeof window.name
window.name = 10
function Foo() {
  this.name = 'bar'
}
Foo.prototype.getName = ()=> {
  console.log(this)
  return this.name+1
}
let foo = new Foo();
let getName = foo.getName;

console.log(getName)
// // ()=> {
//   debugger
//   console.log(this)
//   return this.name+1
// }
console.log(getName())
// window 
// 101
console.log(getName.call(Foo))
// window 
// 101
function Foo() {
  getName = function(){ console.log(1); };
  return this;
}
Foo.getName = function() { console.log(2); };
Foo.prototype.getName = function(){ console.log(3); };
var getName = function() { console.log(4); };
function getName(){ console.log(5); }

Foo.getName(); //
getName(); //
Foo().getName(); //
getName(); //
new Foo.getName(); //
new Foo().getName(); //

4、算法题 'abbbaca'=>'aaca'=>'ca'

  • 栈 出栈 入栈
  • 指针移动到不相同的位置
  • string的length静态方法
//// 'abbbaca'=>'aaca'=>'ca'
/**
 * 删除字符串中出现次数 >= 2 次的相邻字符
 * @param {string}s
 */
let removeDuplicate =(s) =>{
  const stack = [] // Space: O(n)
  let top
  let next
  let i = 0
  while (i < s.length) {  // Time: O(n)
    top = stack[stack.length - 1]
    next = s[i]
    if (next === top) {
      // 字符串中出现了相邻字符
      // 1. 移除栈顶字符
      // 2. 移动指针, 指向下一个不同的字符
      stack.pop()
      while (s[i] === top) i += 1
    } else {
      stack.push(next)
      i += 1
    }
  }
  return stack.join('')  // Time: O(n)
}

let s = 'abbbaca'
let b = removeDuplicates(s)
console.log(b)
  • 没有指针移动
// 'abbaca'=>'aaca'=>'ca'
// 'abbbaca'=>'abaca'
var removeDuplicates = function(S) {
  let stack = [S[0]]
  for (let i = 1; i < S.length; i++) {
    if (S[i] === stack[stack.length - 1]) {
      stack.pop()
    } else {
      stack.push(S[i])
    }
  }
  return stack.join('')
};
let s = 'abbbaca'
let b = removeDuplicates(s)
console.log(b)

//// 'abbbaca'=>'aaca'=>'ca'
  let s = 'abbbbaca'

  const removeDuplicates = function (s) {
    let arr = s.split('')
    let newArr = arr
    while (quDouble(newArr).flag) {
      newArr = quDouble(newArr)
    }
    return newArr.arr.join('')
  };

  function quDouble(arr) {
    debugger
    let minidx = 0
    let flag = false
    for (let i = 0; i < arr.length; i++) {
      minidx = i
      let j = i
      while (arr[i] === arr[j + 1]) {
        flag = true;
        j++
      }
      if (i !== j) {
        arr.splice(i, j-i+1)
      }
    }
    return {
      arr: arr,
      flag: flag
    };
  }

  let newString = removeDuplicates(s)
  console.log(newString)

5、跨域