当前位置:   article > 正文

「随笔」前端面试 | 2023年前端面试基础必备_2023年作为一名前端开发者需要掌握这些,前端面试复习资料参考大纲

2023年作为一名前端开发者需要掌握这些,前端面试复习资料参考大纲

文章目录


前言

本文主要介绍2022年前端面试基础试题


1. CSS 盒子模型(Box Model)是什么?

CSS盒模型本质上是一个盒子,封装周围的HTML元素,它包括:边距,边框,填充,和实际内容。
在这里插入图片描述

  • Margin(外边距) - 清除边框外的区域,外边距是透明的。
  • Border(边框) - 围绕在内边距和内容外的边框。
  • Padding(内边距) - 清除内容周围的区域,内边距是透明的。
  • Content(内容) - 盒子的内容,显示文本和图像。

注:浏览器的兼容性问题
IE5.X 和 6 在怪异模式中使用自己的非标准模型。这些浏览器的 width 属性不是内容的宽度,而是内容、内边距和边框的宽度的总和。
IE8 及更早IE版本不支持设置填充的宽度和边框的宽度属性。
解决IE8及更早版本不兼容问题可以在HTML页面声明 即可。

2. 网页布局有哪些?

2.1 固定布局

静态布局
以像素为基本单位布局,像素是绝对单位

特点:宽度都是固定的
缺点:浏览器无法适配,页面小,内容显示不全,页面大,两侧空白过大

2.2 流动布局

HTML默认布局(DIV+CSS布局)

  • 块级元素(独占一行,宽度100%)
  • 内联元素(从左到右水平分布)

特点:相对单位,根据页面进行等比改变
缺点:文字无法进行流动

2.3 浮动布局(float)

CSS 的 Float(浮动),会使元素向左或向右移动,其周围的元素也会重新排列。
在这里插入图片描述

  • 左浮动(几个浮动的元素放到一起,若有空间,它们将彼此相邻左对齐)float:left
  • 右浮动(几个浮动的元素放到一起,若有空间,它们将彼此相邻右对齐)float:right
  • 左右浮动(两个浮动的元素放到一起,若有空间,它们将彼此左右对齐)

当我们想让两个块级元素再同一行排列是,可以使用浮动布局实现
注:清除浮动,使用 clear:both;
元素浮动之后,周围的元素会重新排列,为了避免这种情况,使用 clear 属性。

特点:图文混排友好,块级元素布局友好
缺点:浮动元素脱离文档流,无法撑起父元素,造成父元素高度坍塌,需配合clear:both

2.4 表格布局

  • 父容器display:table
  • 子容器display:table-cell(空间平均划分:子级容器默认是自动平分宽度沾满父级容器;)

对容器内内垂直居中,等高对齐布局友好
特点:兼容性好,易上手,
缺点:代码冗余,灵活性差,加载慢,SEO不友好

2.5 响应式布局(responsive web design)

  • 百分比布局(bootstrap栅栏系统→传送门
  • rem布局(css3新增单位,移动端友好度极高)
  • 媒体查询@media screen(设置不同类型的媒体条件,适配不同设备pc大中小屏,移动端横竖屏,制作复杂,加载速度相对较慢)
  • flex布局(弹性布局,易上手,兼容IE9及以上)
  • vwvh布局(视窗单位,分为100份,相对视窗实际宽高自动计算适配,适合大数据大屏展示,1px、较小像素不好适配)

特点:适配不同视窗网页结构(pc+手机+平板等),无滚动条,
缺点:上手复杂度高,渲染速度相对较慢

3. HTML5新标签新特性有哪些?

  • 用于绘画的 canvas 元素
  • 用于媒介回放的 video 和 audio 元素
  • 对本地离线存储的更好的支持
  • 新的特殊内容元素,比如 articlefooterheadernavsection
  • 新的表单控件,比如 calendardatetimeemailurlsearch

HTML5新增语义化元素→传送门

4. BFC是什么?

Block Formatting Context 块级格式化上下文
一个BFC区域包含创建该上下文元素的所有子元素,但是不包括创建了新的BFC的子元素的内部元素,BFC是一块块独立的渲染区域,可以将BFC看成是元素的一种属性,拥有了这种属性的元素就会使他的子元素与世隔绝,不会影响到外部其他元素

  • 每个BFC区域只包涵其子元素,不包括子元素的子元素
  • 每个BFC区域都是独立隔绝,互不影响

如何形成BFC区域:
设置浮动,不包括none
设置定位,absoulte或者fixed
行内块显示模式,inline-block
设置overflow,即hiddenautoscroll
表格单元格,table-cell
弹性布局,flex

5. 浏览器加载页面顺序的工作机制是什么?

  • 用户输入网址(首次访问),浏览器向服务器发起请求,服务器返回HTML文件
  • 浏览器开始载入HTML代码,判断标签内是否有标签,若有服务器发出CSS文件的请求,服务器返回这个CSS文件
  • 浏览器继续载入HTML中的部分的代码。因为是异步请求,CSS文件开始渲染页面。
  • 若浏览器在代码中发现一个标签引用了一张图片,向服务器发出请求。此时浏览器不会等到图片加载完毕,而是继续渲染代码。
  • 服务器返回图片文件,影响了后面段落的布局,隐藏浏览器需要重新渲染这部分的代码。
  • 浏览器再代码中发现

6. 如何加快HTML页面加载速度?

  • 删除不必要的空格和注释。
  • 将script和style代码移到外部文件。
  • 通过gulp等代码压缩工具。
  • 减少页面上引用文件数量,能合并就合并。
  • 减少HTTP连接数,下载到后引入。
  • 减少域名查询,DNS查询和解析不同域名耗时较久。如:Javascript、css、图片等资源引用
  • 缓存重用数据
  • 优化页面元素加载顺序,先加载文本后加载图片、多媒体等按需按序加载。
  • 避免使用嵌套table,渲染加载速度慢
  • 指定图像大小和table的大小,可以减少浏览器重新布局渲染

7. CSS实现水平垂直居中的方式

7.1 对单行元素进行居中

.class{
	height: 0.2rem;
	line-height:0.2rem; // 垂直居中
	text-align:center; // 水平居中
	// vertical-align: middle; // 针对行内元素
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

7.2 对文本进行居中

.class{
	display:flex;
	align-items:center; // 垂直居中
	justify-content:center; // 水平居中
}
  • 1
  • 2
  • 3
  • 4
  • 5

7.3 transform的变形居中

.father{
	 position: relative;
}
.child{
	position: absolute;
    top: 50%; 
    left: 50%;
    -webkit-transform: translate(-50%,-50%);
    -ms-transform: translate(-50%,-50%);
    transform: translate(-50%,-50%);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

7.4 table表格居中

.father{
	display:table;
	text align:center;
}
.child{
	display:table cell;
	vertical-align:middle;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

7.5 margin:auto实现居中

.father{
	position:relative;
}
.child{
	width: 50%;  
    height: 50%;  
    overflow: auto;  
    margin: auto;  
    position: absolute;  
    top: 0; left: 0; bottom: 0; right: 0;  
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

7.6 fixed实现居中

.class{
	position:fixed;
	z-index: 99;//层叠属性值
}
  • 1
  • 2
  • 3
  • 4

7.7 margin实现居中

.class{
	margin:0 auto;//根据实际上下边距调整
	display:block;//根据实际实际要求是否转化成行列元素和块级元素
}
  • 1
  • 2
  • 3
  • 4

特点缺点→传送门

8. css常用选择器有哪些?

CSS选择器的作用是从HTML页面中找出特定的某类元素。

  • 通配符选择器 *{属性:属性值;}常用于设置所有HTML标记
  • id 选择器 #id名{属性:属性值;}元素的id值是唯一的,只能对应于文档中某一个具体的元素。
  • 类(class)选择器 .class名{属性:属性值;}大多数HTML元素都可以定义class属性
  • 标签选择器 标签名{属性:属性值;}所有的HTML标记名都可以作为标签选择器,例如abodyph1等等。用标签选择器定义的样式对页面中该类型的所有标签都有效。
  • 伪选择器伪选择器是一种特殊的选择器,它分为伪类选择器伪对象选择器。前者分别对应HTML标记的五种状态:hover:link:focus:visited:active,后者根据对象内部的局部元素定义其样式:first-letter:first-line:before:after
  • 属性选择器 [标签名]{属性:属性值;}注:只有在规定了 !DOCTYPE 时,IE7 和 IE8 才支持属性选择器。在 IE6 及更低的版本中,不支持属性选择。
  • 并集选择器 标签名1,标签名2{属性:属性值;}同时匹配多个选择器,取多个选择器的并集,选择器之间用逗号隔开,如div,p{ }
  • 后代选择器 标签名1 标签名2{属性:属性值;}用来选择特定元素的后代.
  • 子代选择器 标签名1 > 标签名2{属性:属性值;}表示匹配第二个选择器,且为第一个选择器的元素的后代。
  • 兄弟选择器+~标签名1+标签名2{属性:属性值;}相邻兄弟选择器使用+号表示,如p+a{ },表示匹配紧跟第一个选择器并匹配第二个选择器的元素,如紧跟p元素后的a的元素。标签名1~标签名2{属性:属性值;}作用是查找某一个指定元素的后面的所有兄弟结点。

css选择器→传送门

注:样式优先级内联>id选择器>类(class)选择器>标签选择器

9. SEO功能

  • 站点的TITLEKEYWORDSDESCRIPTION等都可以直接在后台进行动态修改和添加;每篇文章,管理者也可以设定不定的标题、关键词和描述,并可以生成地图文件sitemap.xml,以方便搜索引擎收录。
  • 重要的HTML代码放前面。语义化HTML标签。
  • 图片alt属性需要填写相关信息。
  • iframe不会被搜索引擎收录。

10. ES6新增的方法

10.1 两种声明的方式

letconst块级作用域,同一作用域不允许重复声明变量。

  • 变量提升 var声明的变量存在变量提升,即变量可以在声明之前调用,值为undefinedletconst不存在变量提升,即它们所声明的变量一定要在声明后使用,否则报错。
  • 暂时性死区
    var不存在暂时性死区
    letconst存在暂时性死区,只有等到声明变量的那一行代码出现,才可以获取和使用该变量
  • 块级作用域
    var不存在块级作用域
    letconst存在块级作用域
  • 重复声明
    var允许重复声明变量
    letconst在同一作用域不允许重复声明变量
  • 修改声明的变量
    varlet可以
    const声明一个只读的常量。一旦声明,常量的值就不能改变
    使用

注:能用const的情况尽量使用const,其他情况下大多数使用let,避免使用var

10.2 解构赋值

解构赋值就是从目标对象或数组中提取自己想要的变量
默认值

let arr=[1,2]
let [a,b,c=10]=arr //其中的10就是默认值
console.log(a,b,c);
//在浏览器中打印出来的是[1,2,10]
  • 1
  • 2
  • 3
  • 4

交换变量

let arr=[1,2,3]
let [a,b,c=10]=arr //其中的10就是默认值
console.log(a,b,c);  //那么c就被重新赋值
//在浏览器中打印出来的是[1,2,3]
  • 1
  • 2
  • 3
  • 4

将剩余数组赋给一个变量

let [a,b,[...c]] = [1,2,3,4,5,6,7] // a=1,b=2,c=[3,4,5,6,7]
let [a,b,[...c]] = 'hello'
console.log(a,b,c) // h e [llo]
  • 1
  • 2
  • 3

给新的变量名赋值

 let {a,b} = {a:1,b:2} // a=1,b=2
  • 1

10.3 promise方法

通过新建一个 Promise,更加优雅地书写复杂的异步任务。我们之前遇到的异步任务都是一次异步,如果需要多次调用异步函数呢?例如,如果我想分三次输出字符串,第一次间隔 1 秒,第二次间隔 4 秒,第三次间隔 3 秒:

// 地狱式回调
setTimeout(function () {
    console.log("First");
    setTimeout(function () {
        console.log("Second");
        setTimeout(function () {
            console.log("Third");
        }, 3000);
    }, 4000);
}, 1000);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
// 构造 Promise 优化地狱回调
new Promise(function (resolve, reject) {
    setTimeout(function () {
        console.log("First");
        resolve();
    }, 1000);
}).then(function () {
    return new Promise(function (resolve, reject) {
        setTimeout(function () {
            console.log("Second");
            resolve();
        }, 4000);
    });
}).then(function () {
    setTimeout(function () {
        console.log("Third");
    }, 3000);
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

注:resolve 代表一切正常 reject 是出现异常时所调用的

// 拓展Promise "计时器" 代码
new Promise(function (resolve, reject) {
    var a = 0;
    var b = 1;
    if (b == 0) reject("Divide zero");
    else resolve(a / b);
}).then(function (value) {
    console.log("a / b = " + value);
}).catch(function (err) {
    console.log(err);
}).finally(function () {
    console.log("End");
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

Promise 类有 .then() .catch().finally() 三个方法,这三个方法的参数都是一个函数,.then() 可以将参数中的函数添加到当前 Promise 的正常执行序列,.catch() 则是设定 Promise 的异常处理序列,.finally() 是在 Promise 执行的最后一定会执行的序列。 .then() 传入的函数会按顺序依次执行,有任何异常都会直接跳到 catch 序列

10.4 数据类型symbol和map

symbol
symbol 是ES6 引入了一种新的基本数据类型(原始数据类型) Symbol ,表示独一无二的值。它是JavaScript 语言的第七种数据类型,前六种是: undefinednull 、布尔值(Boolean)、字符串(String)、数值(Number)、对象(Object)。

// Symbol语法
let sym1 = Symbol('vitian')
let sym2 = Symbol('vitian')
Symbol('vitian') === Symbol('vitian') // false
sym1 === sym2 // false
// Symbol.for() 重新使用同一个 Symbol 值
let sym1 = Symbol.for('vitian')
let sym2 = Symbol.for('vitian')
sym1 === sym2 // true
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

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

Map
Map是一个类似于对象的数据类型,它是object的升级版,它可以将任何类型的数据作为key值;

// map的写法
let a = new Map();  //创建一个map对象
a.set(name , 'vitian');  //赋值
// 通过get方法获取 map数据类型中的数据
const b = new Map([ ['name','vitian'] , ['age',18] ]);
console.log(b.get('name'));  //获取Map数据类型并在打印输出 'vitian'
// 去重数组的重复对象
let arr = [1, 2, 3, 2, 1, 1]
[... new Set(arr)]	// [1, 2, 3]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

共同点:set、Map可以储存不重复的值
不同点:set是以 [value, value]的形式储存元素,Map是以 [key, value] 的形式储存

10.5 箭头函数

函数参数的默认值

this.$nextTick(function(){
	// Do SomeThing
})
  • 1
  • 2
  • 3
this.$nextTick(()=>{
	// Do SomeThing
})
  • 1
  • 2
  • 3

10.6 async await 异步函数

异步函数 async function 中可以使用 await 指令,await 指令后必须跟着一个 Promise,异步函数会在这个 Promise 运行中暂停,直到其运行结束再继续运行。

// 将异步操作变得像同步操作一样容易,代码变得更好看,增加易读性
async function asyncFunc() {
    await print(1000, "First");
    await print(4000, "Second");
    await print(3000, "Third");
}
asyncFunc();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
// 处理异常的机制将用 try-catch 块实现
async function asyncFunc() {
    try {
        await new Promise(function (resolve, reject) {
            throw "Some error"; // 或者 reject("Some error")
        });
    } catch (err) {
        console.log(err);
        // 会输出 Some error
    }
}
asyncFunc();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

10.7 class 以及 extends继承

新的class写法让对象原型的写法更加清晰,更加面向对象编程的语法。

class Foo{
    static classMethod(){
        return 'vitian';
    }
}
console.log(Foo.classMethod()); // =>vitian
let foo=new Foo();
foo.classMethod();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
// 父类的静态方法可以被子类继承
class Foo{
    static classMethod(){
        return 'vitian';
    }
}
class Bar extends Foo{
}
 
console.log(Bar.classMethod()); // =>vitian
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

10.8 模块化

模块化是指将一个很大的程序文件,拆分为许多个小的文件,然后将多个小文件组合起来。

  • export 命令:用于规定模块的对外接口
  • import 命令:用于输入其他模块提供的功能
//export 暴露方式1 分别暴露 js/a1.js
export let a= 'vitian';
export function b() {
   	return "vitian.vip";
};
//export 暴露方式2 统一暴露 js/a2.js
let a= 'vitian';
function b() {
   	return "vitian.vip";
};
export {a, b};
//export 暴露方式3 默认暴露 js/a3.js
export default {
   	a: 'vitian',
   	change: function(){
       	return "vitian.vip";
   	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
// import 导入方式1 通用的导入方式
import * as _a1 from "js/a1.js"; // 引入 a1.js 模块内容
_a1.a; // vitian
import * as _a2 from "js/a2.js"; // 引入 a2.js 模块内容
_a2.b(); // vitian.vip
import * as _a3 from "js/a3.js"; // 引入 a3.js 模块内容
_a3.default.change(); // vitian.vip

// import 导入方式2 解构赋值形式
import {a,b}  from "js/a1.js"; // 引入 a1.js 模块内容
console.log(a); // vitian
import {a as _a2,b as _b2}  from "js/a2.js"; // 引入 a2.js 模块内容
console.log(_b2); // vitian.vip
import {default as _a3}  from "js/a3.js"; // 引入 3.js 模块内容
console.log(_a3.change()); // vitian.vip

// import 导入方式3 只针对于默认暴露
import _a3 from "js/a3.js"; // 引入 3.js 模块内容
console.log(_a3.change()); // vitian.vip
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

10.9 includes函数

用于判断数组是否包含给定的值,返回一个布尔值

// 判断字符串
var str = 'vitian'
console.log(str.includes('vi'))   // 返回的结果是true
// 判断数组
var arr = ['a','b','c']
console.log(arr.includes('a')) // 返回结果是true
//判断NaN
var arr = ['a','b',NaN]
console.log(arr.includes(NaN))  //返回的记过是true
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

10.10 find()和findIndex()查找函数

find()findIndex()查找函数

 // 用来查找目标元素,找出第一个符合条件的数组,找到就返回该元素,找不到返回undefined.
 array.find((value, index, arr) => {value === '匹配对象'}
 // 用来查找目标元素,找到就返回元素的位置,找不到就返回-1。
 array.findIndex((value, index, arr) => {value === '匹配对象'})
  • 1
  • 2
  • 3
  • 4

11. JS数组增删改查

11.1 增

// 方法1 数组.push():向数组的末尾添加元素 params多个任意类型值
let arr = [1,2],
   	newArr = arr.push(3);
console.log(arr) // push方法会改变原数组,向数组的末尾添加元素 => [1,2,3]
console.log(newArr) // 增后的数组长度 => 3 

// 方法2 数组.unshift():向数组开头添加元素 params多个任意类型值
let arr = [1,2],
   	newArr = arr.unshift(3);
console.log(arr) // unshift方法会改变原数组,向数组开头添加元素 => [3,1,2]
console.log(newArr) // 增后的数组长度 => 3 

// 方法3 数组.concat():向数组的末尾添加元素 params多个任意类型值
let arr = [1,2],
   	newArr = arr.concat(3);
console.log(arr) // concat方法不会改变原数组 => [1,2]
console.log(newArr) // 向数组的末尾添加元素 => [1,2,3] 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

11.2 删

// 方法1 数组.pop():删除数组中最后的那项 params多个任意类型值
let arr = [1,2,3],
   	newArr = arr.pop();
console.log(arr) // pop方法会改变原数组,删除数组中最后的那项 => [1,2]
console.log(newArr) // 被删除的那项 => 3 

// 方法2 数组.shift():删除数组中开头的那项元素 params多个任意类型值
let arr = [1,2,3],
   	newArr = arr.shift();
console.log(arr) // shift方法会改变原数组,删除数组中开头的那项元素 => [2,3]
console.log(newArr) // 被删除的那项 => 1
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

11.3 改

// 数组.splice():数组从索引n开始向后截取n个元素,并在此插入元素n params多个任意类型值
let arr = [1,2,3],
   	newArr = arr.splice(0,1,3);
console.log(arr) // splice方法会改变原数组,从索引0开始向后截取1个元素,并在此插入元素3 => [3,2,3]
console.log(newArr) // 被截取的那项 => [0]

// 拓展1 增 
let arr = [1,2,3],
   	newArr = arr.splice(arr.length-1,0,4);
console.log(arr) //从数组末尾开始向后截取0个元素,并在此插入新元素7 => [1,2,3,4]
console.log(newArr) // 被截取的项 => []

// 拓展2 删 
let arr = [1,2,3],
   	newArr = arr.splice(0,1);
console.log(arr) //从索引0开始向后截取1个元素 => [2,3]
console.log(newArr) // 被截取的项 => [0]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

11.4 查

// slice方法不会改变原数组
let arr = [1,2,3],
   	newArr = arr.slice(0,arr.length);
console.log(arr) //从索引0开始查询到数组末尾的后一项(复制数组) => [1,2,3]
console.log(newArr) // 复制数组 => [1,2,3]

let arr = [1,2,3],
   	newArr = arr.slice(0.9,1.1); // 当x和y为小数时,会先通过parseInt转换为整数在进行查询操作 => 从索引0开始查询到索引为1的元素
console.log(arr) // => [1,2,3]
console.log(newArr) //  => [1]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

12. JS常用的排序方法

12.1 冒泡排序(升序)

冒泡排序法,也叫升序排序法,但是相比起二分法查找只能应用于有序数列

let arr = [1,3,7,5,9];
bubblingFunc(arr){
	if(Array.isArray(arr)){
		if(arr.length==1){
			return arr;
		}
		let data = null;
		for(let i = 0; i< arr.length; i++) {
			for (let j = 0; j< arr.length; j++) {
				if(arr[j] > arr[i]) {
					data = arr[j];
					arr[j] = arr[j + 1];
					arr[j + 1] = data;
				}
			}	
		}
		return arr;
	}
}
console.log(bubblingFunc(arr)); // => [1,3,5,7,9]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

12.2 选择排序(降序)

在未排序序列中找到最小元素,把它放到排序序列起始位置。从剩余未排序序列中继续寻找最小元素,然后放在排序序列末尾。以此类推,直至所有元素排序完成。

let arr = [1,3,7,5,9];
selectionFunc(arr){
	if(Array.isArray(arr)){
		if(arr.length==1){
			return arr;
		}
		let data = null;
		for(let i = 0; i< arr.length-1; i++) {
			let min = i; 
			for (let j = i+1; j< arr.length; j++) {
				min = arr[min] < arr[j] ? j : min
			}
			[arr[i],arr[min]] = [arr[min],arr[i]];	
		}
		return arr;
	}
}
console.log(selectionFunc(arr)); // => [9,7,5,3,1]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

12.3 递归排序(快速)

从数列中取出一个数作为参考,分区过程。将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。对左右区间重复第二步,直到各区间只有一个数。

let arr = [1,3,7,5,9];
recursiveFunc(arr){
	if(Array.isArray(arr)){
		if(arr.length==1){
			return arr;
		}
		let mid= Math.ceil(arr.length / 2);
		let val = arr.splice(mid, 1);
		let left = [];
        let right = [];
		array.forEach((value)=> {
             if (value > val) {
                 left.push(value);
             }
             else {
                 right.push(value);
             }
         });
	     return recursiveFunc(left).concat(val , digui(right));
	}
}
console.log(recursiveFunc(arr)); // => [9,7,5,3,1]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

12.4 插入排序

将要排序的数组分成两部分,每次从后面的部分取出索引最小的值插入前面适当的位置。

let arr = [1,3,7,5,9];
insertFunc(arr){
	if(Array.isArray(arr)){
		if(arr.length==1){
			return arr;
		}
	 	for (let i = 1; i < arr.length; i++) {
            let current = arr[i];
            let preIndex = i - 1;
             while (preIndex >= 0 && arr[preIndex] < current) {
                 arr[preIndex + 1] = arr[preIndex];
                 preIndex--;
             }
             arr[preIndex + 1] = current;
         }
         return arr;
	}
}
console.log(insertFunc(arr)); // => [9,7,5,3,1]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

12.5 sort倒叙

let arr = [1,3,7,5,9];
arr .sort((a,b)=>{
	return b - a;
})
console.log(arr );// => [9,7,5,3,1]

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

12.6 reverse数组元素方向反转

let arr = [1,3,7,5,9];
arr.reverse();
console.log(arr);// => [9,5,7,3,1]
  • 1
  • 2
  • 3

13. JS去重方法

const array = [1,1,2,'a','a','b',true,true,false,undefined,undefined,NaN,NaN];
  • 1

13.1 利用Set()+Array.from()去重

const result = Array.from(new Set(array)) // =>[1,2,a,b,true,false,undefined,NaN]
  • 1

13.2 利用两层循环+数组的splice方法

removeFunc(array) {
  for (let i = 0; i < array.length; i++) {
    for (let j = i + 1; j < array.length; j++) {
      if (array[i] === array[j]) {
        array.splice(j, 1)
        len-- 
        j-- 
      }
    }
  }
  return array
}
const result = removeFunc(array) // =>[1,2,a,b,true,false,undefined,NaN]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

13.3 利用indexOf去重

removeFunc(array) {
  let data = []
  array.forEach(e=>{
	if(data.indexOf(e) === -1) {
		data.push(e)
	}
  })
  return data
}
const result = removeFunc(array) // =>[1,2,a,b,true,false,undefined,NaN]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

13.4 利用includes去重

removeFunc(array) {
  let data = []
  array.forEach(e=>{
	if(!data.includes(e)) {
		data.push(e)
	}
  })
  return data
}
const result = removeFunc(array) // =>[1,2,a,b,true,false,undefined,NaN]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

13.5 利用filter()+indexOf()去重

removeFunc(array) {
  return array.filter((e, i) => {
    return array.indexOf(e) === i
  })
}
const result = removeFunc(array) // =>[1,2,a,b,true,false,undefined,NaN]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

13.6 利用数组Map()去重

removeFunc(array) {
  let map = new Map()
  let data = []
  array.forEach(e=>{
	if (!map.has(e)) { // has()用于判断map是否包为item的属性值
      map.set(e, true) // 使用set()将item设置到map中,并设置其属性值为true
      data.push(e)
    }
  })
  return data 
}
const result = removeFunc(array) // =>[1,2,a,b,true,false,undefined,NaN]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

14. 本地存储的方式

  • cookie 适用标记用户与跟踪用户行为的情况
  • sessionStorage 适用敏感账号一次性登录
  • localStorage 适用长期保存在本地的数据
  • indexedDB 适用存储大量数据的情况、在线文档

存储大小:cookie数据大小不能超过4k,sessionStoragelocalStorage虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大。
有效时间:localStorage存储持久数据,浏览器关闭后数据不丢失除非主动删除数据; sessionStorage数据在当前浏览器窗口关闭后自动删除;cookie设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭。
数据与服务器之间的交互方式:cookie的数据会自动的传递到服务器,服务器端也可以写cookie到客户端; sessionStoragelocalStorage不会自动把数据发给服务器,仅在本地保存。

15. 闭包是什么

闭包是指有权访问另外一个函数作用域中的变量的函数,可以理解为(能够读取其他函数内部变量的函数)

特点: 正常函数执行完毕后,里面声明的变量被垃圾回收处理掉,但是闭包可以让作用域里的 变量,在函数执行完之后依旧保持没有被垃圾回收处理掉。
缺点:闭包会导致内存占用过高,因为变量都没有释放内存。

for (let i = 0; i < 4; i++) {
  setTimeout(()=> {
    console.log(i);
  }, 300);
}
// => 4
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

16. 防抖和节流是什么

  • 防抖: n 秒后在执行该事件,若在 n 秒内被重复触发,则重新计时
  • 节流: n 秒内只运行一次,若在 n 秒内重复触发,只有一次生效

17. ajax是什么

基于JQueryAJAX 不是新的编程语言,而是一种将现有的标准组合在一起使用的新方式。
特点:

  • 可以无需刷新页面而与服务器端进行通信。
  • 允许你根据用户事件来更新部分页面内容。

缺点:

  • 没有浏览历史,不能回退
  • 存在跨域问题(同源)
  • SEO不友好

18.vue组件如何通信

  • 父子组件propsthis.$emit
  • ref 链:父组件要给子组件传值,在子组件上定义一个 ref 属性,这样通过父组件的 $refs 属性就可以获取子组件的值了,也可以进行父子,兄弟之间的传值($parent / $children与 ref类似)
  • 事件总线EventBus:使用一个空的 VUE 实例作为事件总线,自定义事件EventBus.$onEventBus.$offEventBus.$emit
  • vuex

19.组件渲染和更新的过程

  • 初次渲染。解析render函数,触发响应式,监听data属性的getter和setter。执行render函数,生成vnode,pacth(elem,vnode)。
  • 更新过程。修改data,触发setter(setter处于监听状态)、重现执行render,生成newVnode,pacth(elem,vnode)。

20.对mvvm的理解

m:model
v:view
vm:viewModel

dom监听data,反之data通过指令操作dom,即数据驱动视图

21.VUE常见性能优化

  • 使用v-if和v-show、computed、v-for和key、keepalive、data层级不要太深、vue-loader开发
  • 自定义事件及时销毁
  • 使用异步组件
  • 性能优化(图片懒加载、减少http请求数、合理设置http缓存、资源合并与压缩、合并css图片,如雪碧图、并重复的资源请求)
  • 使用ssr

22.介绍vuex

vuex 是一个专门为 vue 构建的状态管理工具,主要是为了解决多组间之间状态共享问题。强调的是集中式管理,(组件与组件之间的关系变成了组件与仓库之间的关系)

vuex 的核心包括:state(存放状态)、mutations(同步的更改状态)、actions(发送异步请求,拿到数据)、getters(根据之前的状态派发新的状态)、modules(模块划分)

state 发布一条新的数据,在 getters 里面根据状态派发新的状态,actions 发送异步请求获取数据,然后在 mutations 里面同步的更改数据。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/581250
推荐阅读
相关标签
  

闽ICP备14008679号