前端,通过面试去学习,基础(原型 闭包 this call new eventloop)

基础

个人感觉基础是比较难回答好的,像原型 闭包 this这些概念因为js的语言设计问题会有些绕,加上一开始是培训的java开发,工作后因工作需要转入前端这一行,js的基础理论知识掌握情况基本为0,只知道jq一把梭,能写function能跑就行,也不愿意去看原型闭包这些比较绕的知识点

不过还是应了那句话,基础建设决定上层建筑,没有打好地基想牢固是很难的,只能缓慢爬坡,有了牢固的地基才能呈指数趋势起飞,还是需要掌握好这些基础知识,灵活运用

自问自答,全部简答,给个大致方向,具体每个问题的详细讲解还要去看对应的长篇大论的博客


原型和原型链

这个问题如果讲得多,可能15分钟讲不完,从几个关键点去回答,普通对象,函数对象,proto,prototype,以及最绕的Object和Function,就像鸡生蛋还是蛋生鸡,我当时学习的过程中不想去死记硬背,背了隔段时间就会忘,所以搞清楚顶层的Object和Function就好理解多了

  • 普通对象只有__proto__,函数对象具有__proto__和prototype
  • 顶层的Object和Function的关系(这一块是最绕的…)
  • Object.proto、Array.__proto__等等都指向Function.prototype
  • 特殊情况Function.__proto__指向自身Function.prototype,比较绕,不像一般的实例对象p.__proto__是指向父级Person.prototype
  • Function.prototype.proto、Number.prototype.__proto__是对象,都指向Object.prototype
  • 最终的Object.prototype指向null
  • 面试可能会考量你对Object和Function互相关系的理解,出一个Object.prototype.toString和Object.toString比较
  • 不扯了…太多了

js不像java是面向对象设计的语言,原型可以用来实现js中的继承,可以方法共享,避免重复占用浪费内存,具体看下面的文章吧
说说原型(prototype)、原型链和原型继承 - 知乎
JavaScript原型链的学习总结_IronKee的博客-CSDN博客

闭包

简单讲,就是外部函数可以访问其他函数内部的变量,一种机制

this指向,JS执行上下文,箭头函数this和普通函数区别

这个问题依然不好回答,有的时候明白但是讲不好,如果是结合题目去答可能会好一些

call/apply/bind

call/apply/bind经常和this一起出现,也有些面试官会问你能不能手写call,如果理解call的过程,可以描述一下,我觉得没必要真的手写

  • call、apply、bind 都是为了改变函数运行时上下文(this指向)而存在的,三者接收的第一个参数都是要绑定的this指向,apply的第二个参数是一个数组,call和bind的第二个及之后的参数作为函数实参按顺序传入,bind不会立即调用,执行的时候才调用,其他两个会立即调用。call,apply,bind
  • 手写call的具体步骤
    – 首先获取传入的上下文,没有的话指定为window
    – context.func = this,拿到当前调用的this,将当前this赋值给上下文中的func,暂时保存
    – 获取arguments
    – 执行context.func
    – 删除context.func
  • 手写call https://zhuanlan.zhihu.com/p/261332524
    Function.prototype.call2 = function (context){
      const ctx = context || window
      ctx.func = this //调用call2时,this是调用call2的方法(call2是在函数对象上)
      //测试用例中这个this打印出来是:[function a]
      const args = Array.from(arguments).slice(1)//保存参数
      //通过在ctx中新建一个 函数对象等于调用时的对象 来调用执行来修改this指向
      const res = arguments.length > 1 ? ctx.func(...args) : ctx.func()
      delete ctx.func//避免造成全局污染
      return res
    }
    
    //测试用例:
    obj={c:2}
    function a(x,y){console.log(this,x,y)}
    a.call(obj,1,2)//{c:2} 1 2
    a.call2(obj,1,2)//{c:2,func:[function a]} 1 2
    
  • 手写apply和call差不多,参数处理成数组,手写bind需要return出去一个函数
new

同样有些面试官会问你能不能手写new,还是要理解new的过程,做了什么

  • new一个构造函数,得到的实例继承了构造器的构造属性(this.name这些)以及原型上的属性
  • 手写new https://www.cnblogs.com/echolun/p/10903290.html
    function _new(fn,...rest){
      //基于fn的prototype构建对象的原型
      const thisObj = Object.create(fn.prototype);
      //将thisObj作为fn的this,继承其属性,并获取返回结果为result
      const result = fn.apply(thisObj,rest);
      //根据result对象的类型决定返回结果
      return typeof result === "object" ? result : thisObj;
    }
    
    function Person(name,age){
      this.name = name;
      this.age = age;
    }
    let person11 = new Person("Lee",21);
    let person22 = _new(Person,"Lee",21)
    
事件循环eventloop

这个题目比较高频,几个答题点,js单线程,宏任务,微任务,一次事件循环中哪个优先,浏览器中与nodejs中事件循环的区别

  • 【JS】深入理解事件循环,这一篇就够了!(必看)
  • 浏览器是多进程的,包含很多线程,其中就包含js引擎线程,也就是js主线程
  • js是单线程的,任务分为同步任务和异步任务,同步任务即立即执行的任务,异步任务则会压入队列中,通过先进先出的机制进行协调
  • 同步的进入主线程,即主执行栈,异步的进入任务队列。主线程内的任务执行完毕为空,会去任务队列读取对应的任务,推入主线程执行。 上述过程的不断重复就是我们说的 Event Loop (事件循环)。
  • 在事件循环中,每进行一次循环操作称为tick
  • 规范中规定,task分为两大类, 分别是 Macro Task (宏任务)和 Micro Task(微任务), 并且每个宏任务结束后, 都要清空所有的微任务
  • 宏任务主要包含:script( 整体代码)、setTimeout、setInterval、I/O、UI 交互事件、setImmediate(Node.js 环境)
    微任务主要包含:Promise、MutaionObserver、process.nextTick(Node.js 环境)
  • 一次事件循环中宏先于微,比如同时存在console.log setTimeout promise,则会先执行宏任务console.log或者执行其他同步任务,再读取任务队列清空微任务,执行微任务promise,再执行宏任务setTimeout
  • nodejs中于浏览器中事件循环的区别,暂时了解不多,待补充…
防抖 节流

这个题目频率也不算很低,答题点有实现过程、思路和应用场景

  • 防抖是触发高频事件后,n秒内函数只会执行一次,如果n秒内高频事件再次触发,则会重新计算时间,事件响应函数在一段事件后才执行,,如果这段时间内在次调用内再次调用,则重新计算执行时间,当预定时间内没有再次调用该函数,则执行事件处理逻辑函数
    – 应用场景,比如页面滚动获取scrollTop值
  • 节流指当高频事件触发时,稀释函数的执行频率,让其只会在n秒内执行一次
    – 应用场景,比如点击登录按钮,1秒内只执行一次
  • 具体实现参考手写防抖节流函数
深拷贝,如何避免循环引用

这个题目也算比较高频,考察的点也比较多,现实工作中如果用到深拷贝,建议使用成熟的lodash.js提供的深拷贝cloneDeep

变量提升

答题点,函数是一等公民,函数声明提升,函数表达式不提示,提升范围

  • JavaScript变量提升
  • JavaScript代码运行之前其实是有一个编译阶段的,变量提升就发生在编译阶段,它把变量和函数的声明提升至作用域的顶端
  • 提升的部分只是变量声明,赋值语句和可执行的代码逻辑还保持在原地不动
  • 提升只是将变量声明提升到变量所在的变量范围的顶端,并不是提升到全局范围
函数调用

4种方式

一些常问到的不太常用的API

列举一些常问到的不太常用的api

  • Object.create() ,创建一个新对象,使用现有的对象来提供新创建的对象的proto,Object.create()
  • Object.assign(),合并对象
  • hasOwnProperty(),判断对象上是否含有要查找的属性,不会去原型链上查找
  • 在ES5的环境中,我们使用Object.getPrototype(obj)来获取原型对象,而在不支持ES5的环境中,我们可以考虑用__proto__这样的非标准方法来当做权宜之计
  • JS数组reduce()方法详解及高级技巧
基础知识考察

let a={},a+1,a+‘1’,‘1’+1,‘1’-1,分别输出什么,这种问题靠猜没用,要掌握js设计规则去记忆

未完待续,持续补充…

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值