2021年可能会遇到的面试题(三)

1.有以下3个判读数组方法,请分别介绍它们之间的区别和劣势

  1. Object.prototype.toString.call()
  2. instanceof
  3. Array.isArray

2.介绍下重绘和回流(Repaint&Reflow),以及如何进行优化

  • 浏览器渲染机制:采用了流式布局模型,浏览器会把HTML解析成DOM,把css解析成CSSOM,DOM 和 CSSOM合并就产生了渲染树(Render Tree)。有了RenderTree,我们就知道了所有节点的样式,然后计算它们在页面上的大小和位置,最后把节点绘制到页面上。由于浏览器流式布局方式使Render Tree的计算通常只需要遍历一次就可以完成,但table及其内部元素除外,它们可能需要多次计算,通常需要花3倍于同等元素的时间,这也是为什么要避免视同table布局的原因之一。
  • 重绘:由于节点的几何属性发生改变或者由于样式发生改变而不会影响布局的,成为重绘,例如outline,visibility,color,background-color等,重绘的代价是高昂的,因为浏览器必须验证DOM树上其他节点元素的可见性。
  • 回流:回流是布局或者几何属性需要改变就称为回流。回流是影响浏览器性能的关键因素,因为其变化涉及到部分页面(或整个页面)的布局更新。一个元素的回流可能会导致了其他所有子元素以及DOM中紧随其后的节点、祖先节点元素的随后的回流
  • 浏览器优化:现代浏览器大多是通过队列机制来批量更新布局,浏览器会把修改操作放在队列中,至少1个浏览器刷新(16.6ms)才会清空队列,但当你获取布局信息的时候,队列中可能会有影响这些属性或者返回的操作,即使没有,浏览器也会有强制清空队列,触发回流与重绘来确保返回正确的值。主要包括以下属性或方法:
    • offsetTop、offsetLeft、offsetWidth、offsetHeight
    • scrollTop、scrollLeft、scrollWidth、scrollHeight
    • clientTop、clientLeft、clientWidth、clientHeight
    • width、height
    • getComputedStyle()
    • getBoundingClientRect()

        所以我们应该避免频繁使用上述属性,它们都会轻质渲染刷新队列。

  • 减少重绘与回流

3.介绍下观察者模式和订阅-发布模式的区别,各自适用于什么场景

观察者模式中主体和观察者是互相感知的。发布-订阅者是借助第三方来实现调度的,发布者和订阅者之间互不感知。

4.聊聊Redux和Vuex的设计思想

不管是Vue,还是React,都需要管理状态,比如组件之间都有共享状态的需要,什么是共享状态?比如一个组件需要使用另一个组件的状态,或者一个组件需要改变另一个组件的状态,都是共享状态。父子组件之间,兄弟组件之间共享状态,往往需要写很多没有必要的代码,比如把状态提升到父组件里,或者给兄弟组件写一个父组件,听听就觉得听啰嗦。如果不对状态进行有效的管理,状态在什么时候,由于什么原因,如何变化就不受控制,很难跟踪和测试了。如果没有经历过这方面的困扰,可以简单理解为会搞得很乱就对了。

在软件开发里,有些通用的思想,比如隔离变化,约定优于配置,隔离变化就是说做好抽象,把一些容易变化的地方找到共性,隔离出来,不要去影响其他几个人的约定,view文件夹里只能放视图,不能放过滤器,过滤器必须放到filter文件夹,那这就是一种约定,约定好之后,我们就不用写一大堆配置文件了,我们要找所有的视图,直接从view 文件夹里找就行。

根据这些思想,对于状态管理的解决思路就是:把组件之间需要共享的状态抽取出来,遵循特定的约定,统一来管理,让状态的变化可以预测,根据这个思路,产生了很多的模式和库。

5.说说浏览器和Node事件循环的区别

6.介绍模块化的发展历程

7.全局作用域中,用const 和 let 声明的变量不在window上,那到底在哪里?如何去获取?

8.cookie和token都存放在header中,为什么不会劫持token?

攻击者通过xss拿到用户的cookie然后就可以伪造cookie,或者通过csrf在同个浏览器下面通过浏览器上会自动带上cookie的特性在通过 用户网站-攻击者网站-攻击者请求用户网站的方式 浏览器会自动带上cookie,但是token不会被浏览器带上,token是放在jwt里面下发给客户端的,而且不一定存储在哪里 不能通过document.cookie 直接拿到,通过jwt+ip 的方式 可以防止被劫持 即使被劫持也是无效的jwt

9.聊聊Vue的双向数据绑定,Model如何改变View,View又是如何改变Model的

从M到V的映射(Data Binding),这样可以大量节省你人肉来 update View 的代码,从V到M的事件监听(DOM Listeners),这样你的model会随着view触发事件而改变。

10.两个数组合并成一个数组

请把两个数组 ['A1','A2','B1','B2','C1','C2','D1','D2'] 和 ['A','B','C','D'],合并为 
['A1','A2','A','B1','B2','B','C1','C2','C','D1','D2','D']

11.用javaScript 写一个函数,输入 int 型,返回整数逆序后的字符串。如输入整型 1234,返回字符串 ‘4321’。要求必须使用递归函数调用,不能用全局变量,输入函数必须只有一个参数传入,必须返回字符串。

function unString(intNum) {
 return parseInt(intNum/10) === 0 ? intNum.toString() : (intNum%10+unString(parseInt(intNum/10)))
}

unString(1234)

12.如何实现call,apply函数

/* 
  call函数
  判断对象是否为函数,即使时定义在函数的原型上的,但是可能出现使用call 等方式调用的情况。
  判断传入上下文对象是否存在,如果不存在,则设置为 window。
  处理传入的参数,截取第一个参数后的所有参数。
  将函数作为上下文对象的一个属性。
  使用上下文对象来调用这个方法,并保存返回结果。删除刚才新增的属性
*/
Function.prototype.myCall = function(context) {
  // 判断调用类型是否为函数
  if (typeof this !== 'function') {
    // 如果不是函数 ,就抛出异常
    throw new TypeError('error')
  }
  // 判断context是否传入,如果未传入就设置为 window
  context = context || window;
  // 将函数调用设为对象的方法
  context.fn = this;
  // 获取参数
  let args = [...arguments].slice(1);
  let result = null;
  // 调用函数
  result = context.fn(...args);
  // 将属性删除
  delete context.fn;
  return result;

}

Function.prototype.myApply = function(context) {
  // 判断调用类型是否为函数
  if (typeof this !== 'function') {
    // 如果不是函数 ,就抛出异常
    throw new TypeError('error')
  }
  // 判断context是否传入,如果未传入就设置为 window
  context = context || window;
  // 将函数调用设为对象的方法
  context.fn = this;
  // 获取参数
  let args = [...arguments].slice(1);
  let result = null;
  // 调用函数
  result = context.fn(args);
  // 将属性删除
  delete context.fn;
  return result;
}

13.简述flux思想

Flux 的最大特点,就是数据的“单向流动”。

1.用户访问 View

2 View 发出用户的 Action

3 Dispatcher 收到 Action,要求 Store 进行相应的更新

4.Store 更新后,发出一个“change”事件

5.View 收到“change”事件后,更新页面

14.谈谈你对this对象的理解

this 是执行上下文中的一个属性,它指向最后一次调用这个方法的对象。在实际开发中,this的指向可以通过四种调用模式来判断。

第一种是函数调用模式,当一个函数不是一个对象的属性时,直接作为函数来调用时,this指向全局对象。

第二种时方法调用模式,如果一个函数作为一个对象的方法来调用时,this指向这个对象。

第三种时构造器调用模式,如果一个函数用new 调用时,函数执行前会新建一个对象,this 指向这个新建的对象。

第四中是 apply、call 和 bind 调用模式,这三个方法都可以显示的指定调用函数的this指向。其中apply 方法接收两个参数,1->this绑定的对象,2-> 参数数组

call方法接收 1->this 绑定的对象,2->c=参数列表,逐个列举。bind通过传入一个对象,返回一个this绑定了传入对象的新函数。这个函数的this指向除了使用new 时会被改变,其他情况下都不会改变。

这个四种方式,使用构造器调用模式优先级最高,然后是apply,call,bind 调用模式,然后是方法调用模式,函数调用模式。

posted @ 2021-12-05 09:54  只做你的向日葵  阅读(20)  评论(0编辑  收藏  举报