小厂面试总结(面试问题篇)

上一篇笔记记录了笔试内容,本篇笔记来记录一下面了两个小厂的面试问题总结吧。希望下一次面试可以成功避开这些坑,回答的更好一些。

两个面试感觉都是一上来就开始撕项目经历,根据项目来深入的问一些问题。

下面就梳理一下内容:

1、 能不能讲讲对webpack的理解以及webpack的工作原理?

webpack是一个用于现代JavaScript应用程序的静态打包工具,webpack在处理应用程序时,会在内部从一个或多个入口构建一个依赖图,将每个项目所需的每一个模块组合成一个或多个bundles(均为静态资源)用于展示内容,依赖图对应映射到项目所需的每个模块,并生成一个或多个bundle
webpack的构建流程:

  1. 初始化流程:从配置文件和Shell语句中读取与合并参数,并初始化需要使用的插件和配置插件等执行环境所需要的参数
  2. 编译构建流程:从Entry出发,针对每个Module串行调用对应的Loader去翻译文件内容,再找到该Moudel依赖的Moudel,递归地进行编译处理
  3. 输出流程:对编译后的Moudle组合成Chunk,把Chunk转换成文件,输出到文件系统中。

2. 能不能讲讲vite和webpack的区别以及各自的优缺点?

首先,先讲讲vite的理解,作为vue团队开发的打包工具,其工作原理是根据源文件之间的依赖关系通过浏览器对ESM规范的支持来解析,将应用中的模块区分为依赖和源码两类。实现按需打包,极大的优化了打包速度。
vite 的核心理念就是借助浏览器原生 ES Modules 能力,当浏览器发出请求时,为浏览器按需提供 ES Module 文件,浏览器获取 ES Module 文件会直接执行,即使首次启动的预构建也是使用速度惊人的esbuild完成
优缺点分析

  • 在首屏、懒加载性能方面,由于webpack本身经过了打包过程,得到了一个完整的模块关系依赖包,因此不存在这方面的性能问题。而对于vite而言,由于unbundle机制,在这方面会存在一定的问题,因此需要做额外的工作来处理。
  • 在服务启动速度方面,webpack需要将所有的模块建立依赖关系打包成一个大文件,速度相对较慢。而vite将应用中的模块区分为依赖和源码两类,进行预构建,无需进行bundle处理,速度会块很多。
  • 在热更新速度方面,webpack在编辑文件后将重新构建文件本身,即使使用动态模块热重载,其更新速度也会随着应用规模的增长显著下降。vite编辑一个文件时,只需要精确地使已编辑的模块与其最近的HMR边界之间的链失效,使HMR更新始终快速,无论应用的大小。同时vite利用http头来加速整个页面的重新加载
  • 在pord环境打包的区别,webpack的构建更加成熟,bundle整体形成完善的依赖关系,同时也有非常多的loader plugin可供选择。vite在生产环境的构建目前用的是Rollup而不是esbuild,这是因为rollup在应用打包方面更加成熟且灵活。
  • 对于生态成熟度而言,无疑webpack拥有一个庞大的生态系统,而vite的生态系统目前是比不上webpack的。

总的来说,vite的使用体验感还是非常不错的。

3、es6篇,讲讲es6新增的特性吧

两次面试一来问的就是es6,包括梳理es6的新特性和使用。所以现在需要整理以下es6相关的内容。

1、let/const关键字

在上一篇博客中我们分析了这两个关键字的使用与var的区别:

  • 一个是作用域区别,这两个关键字声明的变量都是块级作用域,var声明的变量是一个全局作用域的变量。
  • let声明的变量不可重复声明,var声明的变量可以重复声明,会覆盖前一次声明的值。
  • letconst关键字声明的变量不存在变量提升,而var关键字声明的变量存在变量提升。
  • const声明的变量是一个常数,不可修改其指针的指向。但是可以修改指针指向地址的值。因此可以修改引用数据类型的内容。
  • const声明的变量必须赋初值。

2、模板字符串

在es6以前,要输出字符串拼接变量的语句,通常使用占位符console.log('hello' + str);这种方式 。而es6中新增的模板字符串,模板字符串使用反引号 ` (Tab 键上方的符号)来代替普通字符串中的用双引号和单引号。模板字符串可以包含特定语法 ${expression} 的占位符。占位符中的表达式和周围的文本会一起传递给一个默认函数,该函数负责将所有的部分连接起来。

console.log(`hello ${str}`)

输出结果与上面的语句输出结果一致。
同时,模板字符串中支持进行变量运算。

3、模块化导入和导出

默认导出:export default{默认导出成员} 每个模块中只允许默认导出一次
默认导入:import 接收名称 from '模块标识符'
按需导出:export 按需导出成员 每个模块中可以多次按需导出
按需导入:import {s1} from '模块标识符' 按需导入的成员名称必须和按需导出的名称保持一致,可以使用as关键字进行重命名
按需导入可以和默认导入一起使用

4、变量的解构赋值

es6中允许按照一定模式从数组和对象中提取值,对变量进行赋值。
数组解构

const array = ['a','b','c','d'];
let [a,b,c,d] = array

下面括号的每一个变量都对象数组中相应位置的值。
对象的解构

const obj = {
	name:'lili',
	age:'18',
	test: function(){
		console.log('test')
	}
}
let {name,age,test} = obj;
console.log(name);
console.log(age);
console.log(test);
test();

对象内的方法被解构出来后可以直接调用。

对象的简化写法

es6允许在一个大括号内直接写入对象的变量和函数,作为对象的属性和方法。

let name = 'aa';
let change = function(){
    console.log('我们可以改变你');
}
const school = {
    name,
    change,
    improve(){
        console.log("bbb");
    }
}

箭头函数及其特点

es6中允许使用 => 来声明一个函数。

let fn = (a,b)=>{
}
//简写形式
//形参有且只有一个时省略小括号
let fn = n => {}
//代码体只有一条语句时省略花括号
let fn = n => n*n;

箭头函数的特性:

  • this是静态的,this的指向始终指向函数声明时所在作用域下的this值
  • 不能作为构造实例化对象
  • 不能使用arguments变量

因此,箭头函数适合与this无关的回调。

函数参数的默认值

es6中允许给函数参数赋值初始值

//1、形参初始值,具有默认值的参数,一般位置要靠后
function add(a,b,c=10){
    return a+b+c;
}
//2、与解构赋值结合
function connect({host="127.0.0.1",username,password,port}){
    console.log(host)
    console.log(username)
    console.log(password)
    concole.log(port)
}
connect({
    host:'localhost',
    username:'root',
    password:'root',
    port:336
})

rest参数

ES6引入rest参数,用于获取函数的实参,用来代替arguments

//rest 参数
function date(...args){
    concole.log(args);
}
date('阿娇','博智','撕毁');
//rest参数必须要放到参数的最后
function fn(a,b,...args){
    concole.log(a);
    concole.log(b);
    console.log(args);
}
fn(1,2,3,4,5,6);

扩展运算符

…扩展运算符能将数组转换为逗号分隔的序列

//声明一个数组
const arr = ['a','b','c','d'];
//声明一个函数
function test(){
	console.log(argument)
}
test(...arr)//等同于test('a','b','c')

Symbol

ES6 引入了一种新的原始数据类型Symbol,表示独一无二的值。它是JavaScript语言的第七种数据类型,是一种类似于字符串的数据类型
特点:

  1. Symbol的值是唯一的,用来解决命名冲突的问题
  2. Symbol值不能与其他数据进行运算
  3. ​ Symbol定义的对象属性不能使用for...in循环遍历,但是可以使用 Relect.ownKeys来获取对象的所有键名

使用场景:给对象添加属性和方法,表示独一无二的值。

迭代器

迭代器是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署iterator接口,就可以完成遍历操作

  1. ES6创造了一种新的遍历命令for…of循环,lterator接口主要供 for...of消费
  2. 原生具备iterator接口的数据(可用for of遍历)
  • Array
  • Arguments
  • Set
  • Map
  • String
  • TypedArray
  • NodeList
const xiyou = ['1','2','3','4']let iterator = xiyou[Symbol.iterator]();

console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());

Set和Map

ES6 引入了 Set 和 Map 作为新的数据结构。Set 是一种无重复元素的集合,Map 是一种键值对的集合。它们提供了方便的方法来处理数据集合和映射关系。以下是 Set 和 Map 的基本用法示例:

// Set的使用
const set = new Set();
set.add(1);
set.add(2);
set.add(3);
console.log(set.size); // 输出:3
console.log(set.has(2)); // 输出:true

// Map的使用
const map = new Map();
map.set('name', 'Zhangsan');
map.set('age', 20);
console.log(map.size); // 输出:2
console.log(map.get('name')); // 输出:Zhangsan

WeakMap和WeakSet

WeakMap 和 WeakSet 是弱引用版本的 Map 和 Set。它们的特点是,当对象被垃圾回收时,与之关联的键也会被自动删除。这对于避免内存泄漏非常有用。

面向对象方面的性质

es6中引入了类的概念,使得js更像一种面向对象的语言。可以用于定义一个原型类,并用于创建类的实例和类的继承。
知识点:

  1. class声明类
  2. constuctor定义构造函数初始化
  3. extends继承父类
  4. super调用父级构造方法
  5. static定义静态方法和属性
  6. 父类方法可以重写

Generator

Generator 是一种特殊的函数,可以通过 yield 语句暂停和恢复执行。它可以用于实现迭代器、异步操作和惰性求值等。

function* generator() {
  yield 1;
  yield 2;
  yield 3;
}

const iterator = generator();

console.log(iterator.next().value); // 输出: 1
console.log(iterator.next().value); // 输出: 2
console.log(iterator.next().value); // 输出: 3

promise

ES6 引入了 Promise 对象,它提供了一种更优雅的方式来处理异步操作。Promise 可以链式调用,通过 then 和 catch 方法来处理成功和失败的情况。以下是 Promise 的基本用法示例:

function fetchData() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('Data fetched successfully.');
    }, 1000);
  });
}

fetchData()
  .then(data => {
    console.log(data); // 输出:Data fetched successfully.
  })
  .catch(error => {
    console.error(error);
  });

promise的出现解决了异步函数回调地狱的问题。es6梳理出来一些常用的特性就是这些了吧,没注意weakset和weakmap,面试官提起的时候知道有这个东西但是不知道区别呜呜呜呜。然后还有一些js问题,例如原型链,闭包以及this指向问题。一些vue框架的简单问题,都不是很深。今天写累了,明天继续。

讲讲什么叫BFC

BFC应该是我面了三家小厂都问了的问题。BFC(Block Formatting Content)-- 块级格式化上下文。

在JavaScript中,BFC是一种重要的布局概念,是目前最常用的清除浮动的方法,它有以下特点:

  • BFC容器计算高度时包括浮动元素:一个BFC容器会将其内部的浮动元素的高度也计算在内,这有助于防止父元素塌陷并正确包裹浮动元素。
  • 解决内外margin重叠的问题:当相邻元素的margin相遇时,margin合并,导致间距小于预期间距。但是在BFC容器内部,margin不会合并,可以更精确地控制元素之间的间距。

创建BFC的属性

  1. display:inline-block
  2. display:table-cell
  3. overflow:hidden / auto / overlay / scroll

overflow: hidden:当内容溢出容器的边界时,多余的内容将被隐藏,不可见。这意味着不会显示滚动条,也不会提供任何滚动功能。
overflow: auto:如果内容溢出容器的边界,滚动条会出现,允许用户滚动查看被隐藏的内容。如果内容未溢出,滚动条将自动隐藏。
overflow: overlay:这是一个相对较新的值,它与auto类似,但在某些情况下会显示一个轻量级的滚动条,而不是传统的滚动条。它的行为可能会因浏览器的不同而有所变化。
overflow: scroll:无论内容是否溢出,始终显示滚动条,允许用户滚动内容。即使内容未溢出,也会显示滚动条,但会被禁用。

  1. 弹性盒子(display:flex || inline-flex)

总结:

# BFC 容器 Block Formatting Content  块级格式化上下文

- 哪些属性可以触发BFC:

1. float: left || right

2. position: absolute || fixed

- 哪些属性可以创建BFC:

3. display: inline-block

4. display: table-cell ....

5. overflow: hidden || auto || overly || scroll

6. 弹性盒子 (display : flex || inline-flex)

- BFC的特点:

1. bfc容器在计算高度时,会将浮动元素的高度也计算在内

2. 用来解决内外margin重叠问题

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值