高级Web前端JavaScript面试题

JavaScript 常见面试题

高级Web前端必会面试题知识点

一、浅拷贝 VS 深拷贝,手写一个深克隆
  • 其实深拷贝和浅拷贝都是针对的引用类型,JS中的变量类型分为值类型(基本类型)和引用类型;对值类型进行复制操作会对值进行一份拷贝,而对引用类型赋值,则会进行地址的拷贝,最终两个变量指向同一份数据,此时如果对其中一个进行修改,就会影响到另外一个。
  • 根据拷贝的层级不同可以分为浅拷贝和深拷贝,浅拷贝就是只进行一层拷贝,深拷贝就是无限层级拷贝。
  • 浅拷贝:实现方式很简单,实现原理就是遍历对象属性。
    1. slice()
    2. concat()
    3. Object.assign(target, …sources)
    4. ES6 扩展运算符 {…obj} 和 […arr]
    5. 循坏push
  • 深拷贝:实现原理可以就是浅拷贝 + 递归。
    1. JSON.parse(JSON.stringify(obj));
  • 手写实现深拷贝
    答案链接
二、call、apply、bind的区别,手写一个bind函数

答案链接

四、promise的使用方法?常用的API有哪些?
  • 概念:Promise是异步编程的一种解决方案,主要用来解决回调地狱的问题,可以有效的减少回调嵌套。所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。Promise有三个状态:Pending(等待)、Resolved(完成)、Rejected(失败)。
  • 特点:
    1. 对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:Pending(进行中)、Resolved(已完成,又称Fulfilled)和Rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。
    2. 一旦状态改变,就不会再编,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从Pending变为Resolved和从Pending变为Rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果。就算改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。
  • 缺点:
    1. 无法取消Promise,一旦新建它就会立即执行,无法中途取消。和一般的对象不一样,无需调用。
    2. 如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。
    3. 当处于Pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。
  • API:
    1. new Promise 创建实例

    2. PromiseObj.then(resolveFn,rejectFn)

      • resolveFn:就是Promise对象成功的回调处理函数,指向 resolve
      • rejectFn:就是Promise对象失败的回调处理函数
      • 除了第一个 then ,以后的所有的 then 都是上一个 then 中的返回结果
      • then 接收到结果一共有三种情况:
        1. 上一个 then 没有返回值,则就是 undefined
        2. 上一个 then 有普通返回值:数组、数字、字符串、对象。。。
        3. 上一个 then 又返回了一个新的 Promise 对象,如果是上一个 then 里面返回了一个 Promise 对象,则这个 then 的回调处理函数就指向了上一个 then 中返回的 Promise 对象中的 resolve。
    3. Promise.all()

      • all 方法需要接收一个数组作为参数数组中存储的多个 Promise 对象实例
    4. PromiseObj.catch() 错误回调

    5. PromiseObj.resolve() 将一个值,数字,字符串…转换为Promise对象

    6. PromiseObj.reject() 错误回调

    => .then(null, err=> {
        // err
    })
    => new Promise((resolve,reject)=>{
        reject('出错了')
    })
五、ES6的解构赋值
  • 概念:就是快速从对象或者数组中取出成员的一个语法方式
  • 数组赋值:批量声明变量,批量赋值变量
    • 应对批量的参数传递,我们可以使用解构赋值
    • 数据解构变量声明时可以用剩余运算符表示变量被赋值的范围: …
    • 复杂解构 : [ ]
  • 对象赋值:
    • 声明变量的时候 : 大括号里面只写变量名:
    • 可以解构出一个API里面的某个方法
  • 对象的扩展运算符
    • … 剩余运算符:[ …a ] 在数组中,把其他内容放在一个变量之中,往变量里面放;
    • … 扩展运算符:{ …obj } 是向对象上添加的扩展;
六、map 和 forEach的区别
  • map()方法: 创建一个新的数组,其中每一个元素由调用数组中的每一个元素执行提供的函数得来。
  • foreEach()方法: 针对每一个元素执行提供的函数。
  • 区别:
    • 返回结果:
      • forEach()方法不会返回执行结果,而是undefined。也就是说,forEach()会修改原来的数组。
      • map()方法会得到一个新的数组并返回。
    • 执行速度:
      forEach()的执行速度 < map()的执行速度
    • 使用场景:
      • forEach适合于你并不打算改变数据的时候,而只是想用数据做一些事情 – 比如存入数据库或则打印出来。
      • map()适用于你要改变数据值的时候。不仅仅在于它更快,而且返回一个新的数组。这样的优点在于你可以使用复合API(composition)(map(), filter(), reduce()等组合使用)。
  • 总结:
    1. forEach()可以做到的东西,map()也同样可以。反过来也是如此。
    2. map()会分配内存空间存储新数组并返回,forEach()不会返回数据。
    3. forEach()允许callback更改原始数组的元素。map()返回新的数组。
七、如何实现组合继承
八、手写代码实现去除首位空格
  • jquery库提供了$.trim()方法
  • 手写实现 .trim()
    function trimStr(str){
        return str.replace(/(^\s*)|(\s*$)/g,"");
    }
九、手写数组去重并返回重复项
十、浏览器端事件循环(event loop)

参考文章

  • 事件循环(event-loop):主线程从"任务队列"中读取执行事件,这个过程是循环不断的,这个机制被称为事件循环。此机制具体如下:主线程会不断从任务队列中按顺序取任务执行,每执行完一个任务都会检查microtask队列是否为空(执行完一个任务的具体标志是函数执行栈为空),如果不为空则会一次性执行完所有microtask。然后再进入下一个循环去任务队列中取下一个任务执行。
  • 什么需要:因为JavaScript是单线程的。单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。如果前一个任务耗时很长,后一个任务就不得不一直等着。为了协调事件(event),用户交互(user interaction),脚本(script),渲染(rendering),网络(networking)等,用户代理(user agent)必须使用事件循环(event loops)。
十一、JS的基本数据类型,判断方法有哪些?typeof 判断哪个类型会出现问题?
十二、原型链
十三、手写一个柯里化函数
十四、简述ES6的新特性

参考文章

  • 不一样的变量声明:const和let
  • 模板字符串
  • 箭头函数(Arrow Functions)
  • 函数的参数默认值
  • Spread / Rest 操作符
  • 二进制和八进制字面量
  • 对象和数组解构
  • 对象超类
  • for…of 和 for…in
  • ES6中的类 Class
十五、async await的好处
十六、generator yield
十八、ES6都用过哪些新语法
十九、this指向
二十、闭包的原理和实际应用
二十一、cookie storage的区别?什么时候使用
二十二、作用域与作用域链
二十三、es6新语法都有什么?let var const 区别
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值