前端面试总结——原生JS

303 阅读3分钟

1. ES 6 语法知道哪些,分别怎么用?

let,const,箭头函数,Promise,展开操作符,解构赋值等等。

参考阮一峰ES 6

2. Promise、Promise.all、Promise.race 分别怎么用?

  • 背代码 Promise 用法
 function fn(){
     return new Promise((resolve, reject)=>{
         成功时调用 resolve(数据)
         失败时调用 reject(错误)
     })
 }
 fn().then(success, fail).then(success2, fail2)
  • 背代码 Promise.all 用法
 Promise.all([promise1, promise2]).then(success1, fail1)

promise1和promise2都成功才会调用success1

  • 背代码 Promise.race 用法
 Promise.race([promise1, promise2]).then(success1, fail1)

promise1和promise2只要有一个成功就会调用success1; promise1和promise2只要有一个失败就会调用fail1; 总之,谁第一个成功或失败,就认为是race的成功或失败。

3. 手写函数防抖和函数节流

节流(一段时间执行一次之后,就不执行第二次)

const throttle = (fn,delay)=>{
  let canUse = true
  return function() {
    const _this = this
    const args = arguments
    if(canUse){
      fn.apply(_this,args)
      canUse = false
      setTimeout(()=>{
        canUse = true
      },delay)
    }
  }
}

// 测试案例
const throttled = throttle(()=>console.log('hi'),2000)
throttled()
throttled()

注意,有些地方认为节流函数不是立刻执行的,而是在冷却时间末尾执行的(相当于施法有吟唱时间),那样说也是对的。

防抖(一段时间会等,然后带着一起做了)

const debounce = (fn,delay)=>{
  let timerId = null
  return function(){
    const context = this
    const args = arguments
    if(timerId){window.clearTimeout(timerId)}  
    timerId = setTimeout(()=>{
      fn.apply(context,args)
      timerId = null
    },delay)
  }
}

// 测试案例
const debounced = debounce(()=>console.log('hi'),2000)
debounced()
debounced()

4. 手写AJAX

背代码,完整版

 var request = new XMLHttpRequest()
 request.open('GET', '/a/b/c?name=ff', true);
 request.onreadystatechange = function () {
   if(request.readyState === 4 && request.status === 200) {
     console.log(request.responseText);
   }};
 request.send();

背代码,简化版

 var request = new XMLHttpRequest()
 request.open('GET', '/a/b/c?name=ff', true)
 request.onload = ()=> console.log(request.responseText)
 request.send()

5. 这段代码里的 this 是什么?

背代码

fn()
this => window/global

obj.fn()
this => obj

fn.call(xx)
this => xx

fn.apply(xx)
this => xx

fn.bind(xx)
this => xx

new Fn()
this => 新的对象

fn = ()=> {}
this => 外面的 this

this 的值到底是什么?一次说清楚

6. 闭包/立即执行函数是什么?

闭包

立即执行函数

7. 什么是 JSONP,什么是 CORS,什么是跨域?

JSONP

CORS

8. async/await 怎么用,如何捕获异常?

阮一峰的书讲了

async/await 怎么用,如何捕获异常?

9. 常考:如何实现深拷贝?

基本实现(递归能力)

循环引用(考虑问题的全面性,理解weakmap的真正意义)

多种类型(考虑问题的严谨性,创建各种引用类型的方法,JS API的熟练程度,准确的判断数据类型,对数据类型的理解程度)

通用遍历(写代码可以考虑性能优化,了解集中遍历的效率,代码抽象能力)

拷贝函数(箭头函数和普通函数的区别,正则表达式熟练程度)

参考文章

10. 如何用正则实现 trim()?

背代码

String.prototype.trim = function(){
    return this.replace(/^\s+|\s+$/g, '')
}
//或者 
function trim(string){
    return string.replace(/^\s+|\s+$/g, '')
}

11. 不用 class 如何实现继承?用 class 又如何实现?

不用 class 这样实现

function Animal(color) {
  this.color = color
}

Animal.prototype.move = function(){
  console.log('这是原型上的方法哦~move');
}

function Cat(color,name) {
  Animal.call(this,color)
  this.name = name
}

function temp(){}
temp.prototype = Animal.prototype
Cat.prototype = new temp()
Cat.prototype.constructor = Cat

Cat.prototype.say = function(){
  console.log('miaomiao~');
}

// 测试
let cat = new Cat("白色","斑鳜")
cat.say()
cat.move()
cat.color
cat.name

背代码,用 class 就简单了

// 用class的方式
class Animal{
  constructor(color){
    this.color = color
  }
  move(){
    console.log("move~move~");
  }
}

class Dog extends Animal {
  constructor(color,name){
    super(color)
    this.name = name
  }
  say(){
    console.log('wangwang~wangwang~');
  }
}

// 测试
let dog = new Dog("黄色","小黄")
dog.say()
dog.move()
dog.name
dog.color

12. 如何实现数组去重?

参考 segmentfault.com/a/119000001…

13. 送命题:手写一个 Promise

参考 juejin.cn/post/684490…