8月血泪史,助力金九银十

本文出现的问题都是在8月阶段实际面试过程中遇到的,大小公司都有涉及,希望能够助力大家金九银十,也希望自己能够顺利找到工作。现在外面大环境的确太难了……

文中部分题目提供了参考资料以及自己整理的相关答案,可能不一定是最准确的,大家酌情参考。

如涉及到其他文章内容引用没有标明出处的,可以私聊补充更新。

Javascript

1.JS基本数据类型有哪些

基本数据类型:

  1. 字符串(String):表示文本数据,使用引号(单引号或双引号)括起来。例如:"Hello World"。
  2. 数字(Number):表示数值数据,包括整数和浮点数。例如:10、3.14。
  3. 布尔值(Boolean):表示逻辑值,只有两个值:true(真)和false(假)。
  4. null:表示空值,表示一个空对象指针。
  5. undefined:表示未定义的值,表示变量未被赋值。
  6. Symbol:表示唯一的标识符,用于对象属性的键。

【扩展】说一下undefined和null的区别

当谈到 JavaScript 中的 undefined 和 null 时,它们是两个不同的值,但都表示缺少值。它们之间的区别如下:

  1. undefined 是表示变量声明但未赋值的默认值。当尝试访问未初始化的变量时,它的值为 undefined。全局属性 undefined 表示原始值undefined。它是一个 JavaScript 的 原始数据类型 。undefined是全局对象的一个属性。也就是说,它是全局作用域的一个变量。undefined的最初值就是原始数据类型undefined。
  2. 值 null 特指对象的值未设置。它是 JavaScript 基本类型 之一,在布尔运算中被认为是falsy。它是一个特殊的关键字,表示变量不指向任何对象、数组或函数。值 null 是一个字面量,不像 undefined,它不是全局对象的一个属性。null 是表示缺少的标识,指示变量未指向任何对象。把 null 作为尚未创建的对象,也许更好理解。在 API 中,null 常在返回类型应是一个对象,但没有关联的值的地方使用。

2.const、let和var的区别

【参考资料】

面试官:说说var、let、const之间的区别

3.call、apply和bind的区别

  • 三者都可以改变函数的this对象指向。
  • 三者第一个参数都是this要指向的对象,如果如果没有这个参数或参数为undefined或null,则默认指向全局window。
  • 三者都可以传参,但是apply是数组,而call是参数列表,且apply和call是一次性传入参数,而bind可以分为多次传入。
  • bind 是返回绑定this之后的函数,便于稍后调用;apply 、call 则是立即执行 。

【参考】

彻底弄懂bind,apply,call三者的区别

深入了解 call, apply, bind 和模拟实现

5分钟带你搞懂 Javascript 中的this(包含apply、call、bind)

4.对闭包的理解

概念

一个函数和对其周围状态(lexical environment,词法环境)的引用捆绑在一起(或者说函数被引用包围),这样的组合就是闭包(closure)。也就是说,闭包让你可以在一个内层函数中访问到其外层函数的作用域。在 JavaScript 中,每当创建一个函数,闭包就会在函数创建的同时被创建出来。

重点的一句:闭包让你可以在一个内层函数中访问到其外层函数的作用域。

使用场景

  • return一个内部函数,读取内部函数的变量;
  • 函数作为参数
  • IIFE(自执行函数)
  • 封装对象的私有对象和私有方法;

5.new 一个构造函数的过程

用new操作符创建对象时发生的事情:

  • 创建新对象
  • 新对象原型[[prototype]] = 构造函数prototype
  • this 指向新对象
  • 执行构造函数
  • 如果构造函数返回非空对象,就返回这个对象引用,不然返回创建的新对象

函数调用时前面不加new就按普通函数来 执行。加new后对其进行了相应的变动, 按构造函数来执行。

new的具体过程如下:

//例子:
function Person(name,age) {
  this.userName = name;
  this.userAge = age;
}
var personl = new Person('LULU',20)

1、创建一个新的空对象。(即实例对象)

obj = {}

2 、设 置 原 型 链

将新对象obj的 __proto__属性指向构造函数的prototype对象。(即所有实例对象通过__proto__可以访问原型对象。构造函数的原型被其所有实例对象共享。)

obj.__proto__= Person.prototype

3 、将构造函数的this改指向新对象obj并执行函数代码。

(即给实例对象设置属性 userName, userAge并赋值。)

var result = Person.apply(obj,['LULU',20])

4 、如果构造函数中没有人为返回一个对象类型的值,则返回这个新对象obj。否则直接返回那个对象类型值。(一般定义的构造函数中不写返回值。)

if (typeof(result) == 'object') {
  return result;
}else{
  return obj; 
}

【扩展】手动实现一个new操作,参数为构造函数 及其传参

//构造函数
function Person(name,age) {
  this.userName = name;
  this.userAge = age;
}
Person.prototype.sayAge = function(){
  console.Iog(this.userAge)
}
// new操作函数newFun
function newFun() {
  var obj = {};
  Constructor = [].shift.call(arguments);
  obj.__proto__ = Constructor.prototype;
  var ret = Constructor.apply(obj, arguments);
  return typeof ret === 'object' ? ret: obj;
};
//调用 newFun
var s1 = newFun(Person, 'xiaoyun',20);
console.log(s1.userName) //xiaoyun
console.log(s1.sayAge()) //20

备注:[].shift.call(arguments):删除并返回参数列表arguments中第一个参数,即获得构造函数。arguments剩余参数为构数传参。arguments是类数组,没有数组方法shift,可更改shift方法的this指向从而运用到 arguments 上。

6.ES6高阶函数有哪些

ES6中的高阶函数有以下几种:

  1. map:对数组中的每个元素进行操作,并返回一个新的数组。
  2. filter:根据指定的条件过滤出数组中的元素,并返回一个新的数组。
  3. reduce:对数组中的元素进行累加或累积操作,并返回一个结果。
  4. forEach:对数组中的每个元素进行操作,没有返回值。
  5. some:判断数组中是否存在满足指定条件的元素,返回布尔值。
  6. every:判断数组中的所有元素是否都满足指定条件,返回布尔值。
  7. find:查找数组中满足指定条件的第一个元素,并返回该元素。
  8. findIndex:查找数组中满足指定条件的第一个元素的索引,并返回该索引。
  9. sort:对数组中的元素进行排序。
  10. flat:将多维数组转换为一维数组。
  11. map、filter、reduce等方法的变种,如flatMap、find、findIndex等。

这些高阶函数可以使代码更简洁、可读性更高,并且提供了一种函数式编程的方式来操作数组。

Typescript

1.TS对比JS的优势有哪些

CSS

1.说下什么是BFC

BFC到底是什么东西

BFC 全称:Block Formatting Context, 名为 "块级格式化上下文"。

W3C官方解释为:BFC它决定了元素如何对其内容进行定位,以及与其它元素的关系和相互作用,当涉及到可视化布局时,Block Formatting Context提供了一个环境,HTML在这个环境中按照一定的规则进行布局。

简单来说就是,BFC是一个完全独立的空间(布局环境),让空间里的子元素不会影响到外面的布局。那么怎么使用BFC呢,BFC可以看做是一个CSS元素属性

怎样触发BFC

这里简单列举几个触发BFC使用的CSS属性

  • overflow: hidden
  • display: inline-block
  • position: absolute
  • position: fixed
  • display: table-cell
  • display: flex

【参考】

面试官:请说说什么是BFC?大白话讲清楚

区块格式化上下文

Vue

1.Vue2、3的模版编译渲染过程有哪些区别

2.虚拟Dom的优势是什么?性能一定更好吗?

虚拟 DOM (Virtual DOM )这个概念相信大家都不陌生,从 React 到 Vue ,虚拟 DOM 为这两个框架都带来了跨平台的能力(React-Native 和 Weex)

实际上它只是一层对真实DOM的抽象,以JavaScript 对象 (VNode 节点) 作为基础的树,用对象的属性来描述节点,最终可以通过一系列操作使这棵树映射到真实环境上

在Javascript对象中,虚拟DOM 表现为一个 Object对象。并且最少包含标签名 (tag)、属性 (attrs) 和子元素对象 (children) 三个属性,不同框架对这三个属性的名命可能会有差别

创建虚拟DOM就是为了更好将虚拟的节点渲染到页面视图中,所以虚拟DOM对象的节点与真实DOM的属性一一照应

优点:

保证性能下限: 框架的虚拟 DOM 需要适配任何上层 API 可能产生的操作,它的一些 DOM 操作的实现必须是普适的,所以它的性能并不是最优的;但是比起粗暴的 DOM 操作性能要好很多,因此框架的虚拟 DOM 至少可以保证在你不需要手动优化的情况下,依然可以提供还不错的性能,即保证性能的下限; 无需手动操作 DOM: 我们不再需要手动去操作 DOM,只需要写好 View-Model 的代码逻辑,框架会根据虚拟 DOM 和 数据双向绑定,帮我们以可预期的方式更新视图,极大提高我们的开发效率;

跨平台: 虚拟 DOM 本质上是 JavaScript 对象,而 DOM 与平台强相关,相比之下虚拟 DOM 可以进行更方便地跨平台操作,例如服务器渲染、weex 开发等等。

缺点:

无法进行极致优化: 虽然虚拟 DOM + 合理的优化,足以应对绝大部分应用的性能需求,但在一些性能要求极高的应用中虚拟 DOM 无法进行针对性的极致优化。

【参考资料】

面试官:什么是虚拟DOM?如何实现一个虚拟DOM?说说你的思路

3.Vue2和Vue3的响应式区别

  • Vue2中响应式是通过defineProperty实现的
  • Vue3中响应式是通过ES6的Proxy实现的
  • Vue3中实现响应式数据的方法是ref和reactive

【扩展内容】 盘点 Vue3 与 Vue2 的区别

4.ref和reactive的区别

reactive特点

  • reactive的参数一般是对象或者数组,他能够将复杂数据类型变为响应式数据。
  • reactive的响应式是深层次的,底层本质是将传入的数据转换为Proxy对象

ref特点

  • ref的参数一般是基本数据类型,也可以是对象类型
  • 如果参数是对象类型,其实底层的本质还是reactive,系统会自动将ref转换为reactive,例如 ref(1) ===> reactive({value:1})
  • 在模板中访问ref中的数据,系统会自动帮我们添加.value,在JS中访问ref中的数据,需要手动添加.value
  • ref的底层原理同reactive一样,都是Proxy

5.Vue的双向数据绑定/响应式原理

【参考资料】

面试官:双向数据绑定是什么

6.Vue2为什么不能监控到数组/对象的属性变更

首先Object.defineProperty是可以监听部分数组的更新动作的,但是由于它是通过遍历的方式来实现,当数组数据量小的时候没有问题,但是当数据量大的时候,处理上会出现明显的性能问题。也是出于“性能代价和获得的用户体验收益不成正比”的原因,所以Vue2没有去实现监听。Vue3的Proxy的劫持方式完美解决了这个问题。

7.说下Vue中的Slot,使用场景

使用场景

通过插槽可以让用户可以拓展组件,去更好地复用组件和对其做定制化处理

如果父组件在使用到一个复用组件的时候,获取这个组件在不同的地方有少量的更改,如果去重写组件是一件不明智的事情

通过slot插槽向组件内部指定位置传递内容,完成这个复用组件在不同场景的应用

比如布局组件、表格列、下拉选、弹框显示内容等

分类

slot可以分来以下三种:

  • 默认插槽
  • 具名插槽

    • 子组件用name属性来表示插槽的名字,不传为默认插槽
  • 作用域插槽

    • 子组件在作用域上绑定属性来将子组件的信息传给父组件使用,这些属性会被挂在父组件v-slot接受的对象上。父组件中在使用时通过v-slot:(简写:#)获取子组件的信息,在内容中使用

      
      
      
       
      
      
      
      
  • 小结:

    • v-slot属性只能在