前端面试题

2,576 阅读23分钟

1. HTML面试题

行内元素有哪些?块级元素有哪些? 空(void)元素有哪些?

行内元素:span img input

块级元素: div footer header section p h1...h6

空元素:br hr

元素之间的转换问题: display: inline; 把某元素转换成了行内元素 ===>不独占一行的,并且不能设置宽高 display: inline-block; 把某元素转换成了行内块元素 ===>不独占一行的,可以设置宽高 display: block; 把某元素转换成了块元素 ===>独占一行,并且可以设置宽高

页面导入样式时,使用link和@import有什么区别?

区别一:(兼容性)link先有,@import后有

区别二:加载顺序区别,先加载link 后加载@import

title与h1的区别、b与strong的区别、i与em的区别?

title与h1的区别:

定义: title:概括了网站信息,可以告诉搜索引擎或者用户关于这个网站的内容主题是什么 h1:文章主题内容,告诉蜘蛛我们的网站内容最主要是什么 区别: title他是显示在网页标题上、h1是显示在网页内容上 title比h1添加的重要 (title > h1 ) ==》对于seo的了解 场景: 网站的logo都是用h1标签包裹的

b与strong的区别:

定义: b:实体标签,用来给文字加粗的。 strong:逻辑标签,用来加强字符语气的。 区别: b标签只有加粗的样式,没有实际含义。 strong表示标签内字符比较重要,用以强调的。 题外话:为了符合css3的规范,b尽量少用该用strong就行了。

i与em的区别:

定义: i:实体标签,用来做文字倾斜的。 em:是逻辑标签,用来强调文字内容的 区别: i只是一个倾斜标签,没有实际含义。 em表示标签内字符重要,用以强调的。 场景: i更多的用在字体图标,em术语上(医药,生物)。

img标签的title和alt有什么区别?

区别一

title是鼠标放到图片上的提示

alt是图片没加载出来的默认显示东西

区别二

在seo层面上,要加入alt属性来描述这张图是什么内容或者关键字

png、jpg、gif 这些图片格式解释一下,分别什么时候用?

png: 无损压缩,尺寸比jpg大,适合做小图标

jpg: 采用压缩算法,有点失真,比png体积小,适合做中大图片

gif: 一般是动图

webp: 同时支持有损或者无损压缩,webp体积小,兼容性不好

如何关闭iOS键盘首字母自动大写

加一个属性autocapitalize='off' 即可

<input type="text" autocapitalize='off'>

怎么让Chrome支持小于12px 的文字?

chrome默认字体是16px

解决方法: 采用CSS3里的缩放transform:scale

<style type="text/css">
div{
    font-size:10px;
}
div span{
    display: inline-block;
    -webkit-transform:scale(1.6);
}
</style>

ios系统中元素被触摸时产生的半透明灰色遮罩怎么去掉

设置tap-highlight-color: rgba(0,0,0,0)

<style>
    a,button,input,textarea{
        -webkit-tap-highlight-color: rgba(0,0,0,0);
    }
</style>

webkit表单输入框placeholder的颜色值能改变吗?

<style type="text/css">
    input::-webkit-input-placeholder{
        color:red;
    }
</style>

禁止ios 长按时触发系统的菜单,禁止ios&android长按时下载图片

touch-callout: none

user-select:none

禁止ios 长按时触发系统的菜单,禁止ios&android长按时下载图片
html,body{
    touch-callout: none;
    -webkit-touch-callout: none;
    
    user-select:none;
    -webkit-user-select:none;
}

禁止ios和android用户选中文字

html,body{
    user-select:none;
    -webkit-user-select:none;
}

HTML5语义化

  1. 易读性和维护性更好。
  2. seo成分会更好,蜘蛛抓取更好。
  3. IE8不兼容HTML5标签的。解决:可以通过html5shiv.js去处理。

meta viewport 是做什么用的,怎么写?

HTML 5 有哪些标签?

H5 是什么?

Canvas和Svg区别是什么

2. CSS面试题

介绍一下CSS的盒子模型

css盒子模型有两种: 标准盒模型 和 IE盒子模型

标准盒子模型 (四个部分): margin + border + padding + content

IE盒子模型(两个部分): margin + content( border + padding + content )

通过css转换盒子模型
    box-sizing:content-box  标准盒子模型
    box-sizing:border-box   IE盒子模型

line-height和height区别(大厂)

区别就是盒子高度

line-height 强调的是每一行文字的高,如果文字换行,整个盒子高度会增大(行数*行高)

height 是一个死值,就是这个盒子的高度

CSS选择符有哪些?哪些属性可以继承?

列举几个就行

CSS选择符:

通配符(*)

id选择器(#)

类选择器(.)

相邻选择器 (+) //选择下一个兄弟

后代选择器 (ul li)

子元素选择器(>)

CSS属性哪些可以继承

文字系列:font-size,color,line-height,text-align....

CSS属性哪些不可以继承

border,padding,margin.....

CSS优先级如何计算?

优先级: !important > 内联样式 > id > class > 标签 > 通配

CSS权重计算:(权重值)	
内联样式	      1000    
id选择器	       100     
类选择器	       10      
标签&伪类选择器	 1		
通配符(> < + ...)  0       

用CSS画一个三角形

用边框(border)画

盒子宽高设为0,先把全部边框设置为透明,三角形在哪就给哪个边框颜色,尺寸就可以了

一个盒子不给宽度和高度如何水平垂直居中?

最简单方法:弹性盒子

display:flex;
justify-content: center;
align-items: center;

第二种相对定位:

image-20230113152214017

display有哪些值?说明他们的作用。

display值:

none 隐藏元素 block 把某某元素转换成块元素 inline 把某某元素转换成内联元素 inline-block 把某某元素转换成行内块元素

对BFC规范(块级格式化上下文:block formatting context)的理解?

BFC就是页面上隔离的独立容器.容器子元素不会影响到外面元素

了解BFC : 块级格式化上下文。

BFC的原则:如果一个元素具有BFC,那么内部元素再怎么弄,都不会影响到外面的元素。

如何触发BFC: float的值非none overflow的值非visible display的值为:inline-block、table-cell... position的值为:absoute、fixed

清除浮动有哪些方式?

  1. overflow:hidden(触发bfc)

  2. 多添加一个盒子,盒子样式clear:both

  3. after方式

    ul:after{
    	content: '';
    	display: block;
    	clear: both;
    

    }

在网页中的应该使用奇数还是偶数的字体?为什么呢?

偶数 : 让文字在浏览器上表现更好看。

另外说明:ui给前端一般设计图都是偶数的,这样不管是布局也好,转换px也好,方便一点。

有几种定位?分别是根据什么定位的?

position有哪些值?有什么作用?

static [默认] 没有定位

fixed 固定定位,相对于窗口定位

relative 相对定位,相对于自身定位,不脱离文档流(占位置)

absolute 相对于第一个有relative 父元素定位,脱离文档流(会飘起来,不占位置)

relative和absolute区别

  1. relative不脱离文档流 、absolute脱离文档流
  2. relative相对于自身 、 absolute相对于第一个有relative的父元素
  3. relative如果写了left、right、top、bottom ==》只有left、top absolute如果有left、right、top、bottom ==》left、right、top、bottom

写一个左中右布局占满屏幕,其中左、右俩块固定宽200,中间自适应宽,要求先加载中间块,请写出结构及样式。

双飞翼布局,通过margin-left:-100%,-200%控制左右两块

image-20230113154929085

什么是CSS reset?

reset.css 就是用来重置css样式(冗余大,性能差)

normalize.css 为了增强跨浏览器渲染的一致性,一个CSS 重置样式库。(性能更好)

css sprite是什么,有什么优缺点

sprite就是精灵图/雪碧图

1.sprite是什么

就是把多个小图标合并成一个大图标

2.sprite优缺点

优点:减少http请求次数,提升性能

缺点:维护性比较差(一个小图标修改,大图标就要改)

display: none;与visibility: hidden;的区别

  1. 占用位置的区别 display: none; 是不占用位置的 visibility: hidden; 虽然隐藏了,但是占用位置(visibility:可视性看不见)
  2. 重绘和回流的问题(可以不说)

visibility: hidden; 、 display: none; 产生重绘 display: none; 还会产生一次回流

产生回流一定会造成重绘,但是重绘不一定会造成回流。

产生回流的情况:改变元素的位置(left、top...)、显示隐藏元素.... 产生重绘的情况:样式改变、换皮肤

opacity 和 rgba区别

共同性:都可以实现透明效果

opacity 取值范围0到1之间,0表示完全透明,1表示不透明

rgba R表示红色,G表示绿色,B表示蓝色,取值可以在正整数或者百分数。A表示透明度取值0到1之间

区别:继承的区别

opacity会继承,RGBA不会继承

opacity会继承父元素的opacity属性,而RGBA设置的元素的后代元素不会继承不透明属性。

::before 和 :after中双冒号和单冒号 有什么区别?解释一下这2个伪元素的作用。(缺)

  1. 区别 :是伪类、::伪元素 ===》是为了做区分

    2.是什么?作用 元素before之前 、 元素after之后 作用:清除浮动、样式布局上也有作用

rem和em区别

相对于font-size

em是根据父元素的font-size rem是根据根(html)元素的font-size

rem是统一的参考标准(html元素),因此用的比较方便

image-20230114112616694

自适应

自适应就是自适应屏幕尺寸

淘宝无限适配【移动端】:淘宝无限适配 + 布局单位使用rem

image-20230114140905777

image-20230114141004433

响应式

1. 是什么?
	一个URL可以响应多端
2. 语法结构
	@media only screen and (max-width: 1000px){  //@media 设置响应式条件
		ul li:last-child{
			display: none;
		}
	}

	only : 可以排除不支持媒体查询的浏览器
	screen : 设备类型
	max-width | max-height
	min-width | min-height 
3. 响应式图片【性能优化】 
	<picture>   //H5新增标签picture
		<source srcset="1.jpg" media='(min-width:1000px)'>  //media响应式图片
		<source srcset="2.jpg" media='(min-width:700px)'>
		<img srcset="3.jpg">
	</picture>

布局方案

一、什么情况下采用响应式布局

数据不是特别多,用户量不是特别大,纯展示类的项目适合响应式布局

例如:公司的官网、专题页面

特别追求性能的项目,不太适合响应式,因为如果添加了很多的响应式就会造成加载速度变慢。

二、pc + 移动端应该做什么样的布局方案 注意:访问量还可以或者比较大,类似于淘宝网。

pc是一套,会加入一点点响应式。
移动端是一套,会使用自适应的布局方式。

三、pc的设计图

ui:1980
笔记本电脑:1280
ui图的宽度和电脑的宽度不对应该怎么办?
	1. 把ui图进行等比缩放,缩放成和电脑一样的尺寸
	2. 换1980的电脑

四、移动端的设计图

宽度:750
因为750设计图/2就是375,正好是iphone6的尺寸,我们要把iphone6的尺寸做为基准点。

必考:如何垂直居中?

必考:flex 怎么用,常用属性有哪些?

flex布局怎么把元素搞到页面四角处

3. JavaScript+ES6面试题

面试题:延迟加载JS有哪些方式?

延迟加载: async deffer

defer : 等html全部解析完成,才会执行js代码,顺次执行js脚本。 async : async是和html解析同步的(一起的),不是顺次执行js脚本(谁先加载完谁先执行)。

JS数据类型有哪些?

基本类型:string number boolean undefined null

引用类型:object

JS数据类型考题

字符串很厉害,和任何东西相加,都变成字符串

NAN 是一个数值类型,但是值不确定

console.log( true + 1 );     			//2
console.log( 'name'+true );  			//nametrue
console.log( undefined + 1 ); 		//NaN(是一个数值类型)
console.log( typeof undefined );    //undefined
console.log( typeof(NaN) );       //number
console.log( typeof(null) );      //object

null和undefined的区别

  1. 作者在设计js的都是先设计的null(为什么设计了null:最初设计js的时候借鉴了java的语言)
  2. null会被隐式转换成0,很不容易发现错误。
  3. 先有null后有undefined,出来undefined是为了填补之前的坑。

具体区别:JavaScript的最初版本是这样区分的:

null是一个表示"无"的对象(空对象指针),转为数值时为0;

undefined是一个表示"无"的原始值,转为数值时为NaN。

==和===有什么不同

== 比较的是值 ==是通过valueOf隐式转换后比较的

string == number || boolean || number ....都会隐式转换
		通过valueOf转换(valueOf() 方法通常由 JavaScript 在后台自动调用,并不显式地出现在代码中。)

=== 除了比较值,还要比较类型

JS微任务和宏任务

  1. js是单线程的语言。
  2. js代码执行流程:同步执行完==》事件循环 同步的任务都执行完了,才会执行事件循环的内容 进入事件循环:请求、定时器、事件....
  3. 事件循环中包含:【微任务、宏任务】 微任务:promise.then 宏任务:setTimeout..

要执行宏任务的前提是清空了所有的微任务

流程:同步==》事件循环【微任务和宏任务】==》微任务==》宏任务=》微任务...

JS作用域考题(重要)

  1. 除了函数外,js是没有块级作用域。
  2. 作用域链:内部可以访问外部的变量,但是外部不能访问内部的变量。 注意:如果内部有,优先查找到内部,如果内部没有就查找外部的。
  3. 注意声明变量是用var还是没有写(window.)
  4. 注意:js有变量提升的机制【变量悬挂声明】
  5. 优先级:声明变量 > 声明普通函数 > 参数 > 变量提升

面试的时候怎么看:

  1. 本层作用域有没有此变量【注意变量提升】
  2. 注意:js除了函数外没有块级作用域
  3. 普通声明函数是不看写函数的时候顺序
js作用域考题
##### 考题一:

```
function c(){
	var b = 1;
	function a(){
		console.log( b );  //undefined(变量提升)
		var b = 2;
		console.log( b );  //2
	}
	a(); 
	console.log( b );  //1
}
c();
```

##### 考题二:

```
var name = 'a';
(function(){
	if( typeof name == 'undefined' ){
		var name = 'b';
		console.log('111'+name);  //111b
	}else{
		console.log('222'+name); //?
	}
})()
```

##### 考题三:
function fun( a ){
	var a = 10;
	function a(){}
	console.log( a );   //10
}
fun( 100 );  //100 参数优先级大

JS对象考题

JS对象注意点:

```
1. 对象是通过new操作符构建出来的,所以对象之间不想等(除了引用外);
2. 对象注意:引用类型(共同一个地址);
3. 对象的key都是字符串类型;
4. 对象如何找属性|方法;
	查找规则:先在对象本身找 ===> 构造函数中找 ===> 对象原型中找 ===> 构造函数原型中找 ===> 对象上一层原型查找
```

##### 考题一:

```
 [1,2,3] === [1,2,3]   //false
```

##### 考题二:

```
var obj1 = {
	a:'hellow'
}
var obj2 = obj1;
obj2.a = 'world';
console.log(obj1); 	//{a:world}
(function(){
	console.log(a); 	//undefined
	var a = 1;
})();
```

##### 考题三:

```
var a = {}
var b = {
	key:'a'
}
var c = {
	key:'c'
}

a[b] = '123';
a[c] = '456';

console.log( a[b] ); // 456
```

JS作用域+this指向+原型 考题

##### 考题一:

```
function Foo(){
	getName = function(){console.log(1)} //注意是全局的window.
	return this;
}

Foo.getName = function(){console.log(2)}
Foo.prototype.getName = function(){console.log(3)}
var getName = function(){console.log(4)}
function getName(){
	console.log(5)
}

Foo.getName();    //2
getName(); 		  //4
Foo().getName();  //1
getName();		  //1
new Foo().getName();//3
```

##### 考题二:

```
var o = {
	a:10,
	b:{
		a:2,
		fn:function(){
			console.log( this.a ); // 2
			console.log( this );   //代表b对象
		}
	}
}
o.b.fn();
```

##### 考题三:

```
window.name = 'ByteDance';
function A(){
	this.name = 123;
}
A.prototype.getA = function(){
	console.log( this );
	return this.name + 1;
}
let a = new A();
let funcA = a.getA;
funcA();  //this代表window
```

##### 考题四:

```
var length = 10;
function fn(){
	return this.length + 1;
}
var obj = {
	length:5,
	test1:function(){
		return fn();
	}
}
obj.test2 = fn;
console.log( obj.test1() ); 							//1
console.log( fn()===obj.test2() ); 				//false
console.log( obj.test1() == obj.test2() ); //false
```

JS判断变量是不是数组,你能写出哪些方法?

写三个差不多了

方式一: isArry (一定要写)

var arr = [1,2,3];
console.log( Array.isArray( arr ) );

方式二: instanceof (可写)

var arr = [1,2,3];
console.log( arr instanceof Array );

方式三: prototype

var arr = [1,2,3];
console.log( Object.prototype.toString.call(arr).indexOf('Array') != -1 ); 是数组

方式四:isPrototypeOf()

var arr = [1,2,3];
console.log(  Array.prototype.isPrototypeOf(arr) )

方式五:constructor

var arr = [1,2,3];
console.log(  arr.constructor.toString().indexOf('Array') > -1 )

slice是干嘛的、splice是否会改变原数组

面试前数组方法要过一遍

1.slice是用来截取的

参数可以写slice(3),slice(1,3) ,slice(-3)

返回的是一个新数组

image-20230114080947415

  1. splice 功能有:插入、删除、替换 返回:删除的元素 该方法会改变原数组

image-20230114081439634

image-20230114081500219

arr4在索引值为1的位置删除并且插入一个'你好'

image-20230114081542305

JS数组去重

写个三种差不多了

方式一(最简单): new Set

var arr1 = [1,2,3,4,2,1];
new Set(arr1);   //变成Set对象(Set里面的值不重复)
Array.from(new Set(arr1))   //将Set转化为数组

方式二: indexOf

数组中indexOf == -1 就是说明没有重复值

var arr2 = [1,2,3,2,4,1];
function unique( arr ){
	var brr = [];
	for( var i=0;i<arr.length;i++){
		if(  brr.indexOf(arr[i]) == -1 ){   //核心步骤,如果这个元素就push
			brr.push( arr[i] );
		}
	}
	return brr;
}
console.log( unique(arr2) );

方式三: sort

var arr3 = [1,2,3,2,4,1];
function unique( arr ){
	arr = arr.sort();           //[1,1,2,2,3,4]
	var brr = [];
	for(var i=0;i<arr.length;i++){
		if( arr[i] !== arr[i-1]){
			brr.push( arr[i] );
		}
	}
	return brr;
}
console.log( unique(arr3) );

找出多维数组最大值

通过forEach + Math.max

function fnArr(arr){
	var newArr = [];
	arr.forEach((item,index)=>{
		newArr.push( Math.max(...item)  )
	})
	return newArr;
}
console.log(fnArr([
	[4,5,1,3],
	[13,27,18,26],
	[32,35,37,39],
	[1000,1001,857,1]
]));

给字符串新增方法实现功能

通过原型

给字符串对象定义一个addPrefix函数,当传入一个字符串str时,它会返回新的带有指定前缀的字符串,例如:

console.log( 'world'.addPrefix('hello') ) 控制台会输出helloworld

解答:
String.prototype.addPrefix = function(str){
	return str  + this;
}
console.log( 'world'.addPrefix('hello') )

找出字符串出现最多次数的字符以及次数(高频)

把字符出现次数放在一个对象里

var str = 'aaabbbbbccddddddddddx';
var obj = {};
for(var i=0;i<str.length;i++){    //循环遍历数组,统计出现次数
	var char = str.charAt(i);
	if( obj[char] ){
		obj[char]++;
	}else{
		obj[char] = 1;
	}
}
console.log( obj );     // {a:3,b:5,c:2,d:10,x:1}
//统计出来最大值
var max = 0; 
for( var key in obj ){
	if( max < obj[key] ){
		max = obj[key];
	}
}
//拿最大值去对比
for( var key in obj ){
	if( obj[key] == max ){
		console.log('最多的字符是'+key);
		console.log('出现的次数是'+max);
	}
}

new操作符具体做了什么(高频)

  1. 创建了一个空的对象
  2. 将空对象的原型,指向于构造函数的原型
  3. 将空对象作为构造函数的上下文(改变this指向)
  4. 对构造函数有返回值的处理判断
function Fun( age,name ){
	this.age = age;
	this.name = name;
}
function create( fn , ...args ){
	//1. 创建了一个空的对象
	var obj = {}; //var obj = Object.create({})
	//2. 将空对象的原型,指向于构造函数的原型
	Object.setPrototypeOf(obj,fn.prototype);
	//3. 将空对象作为构造函数的上下文(改变this指向)
	var result = fn.apply(obj,args);
	//4. 对构造函数有返回值的处理判断
	return result instanceof Object ? result : obj;
}
console.log( create(Fun,18,'张三')   )

闭包

外部函数包裹内容函数,内部函数的作用范围

1. 闭包是什么
	闭包是一个函数加上到创建函数的作用域的连接,闭包“关闭”了函数的自由变量(变量不会回收)。
2. 闭包可以解决什么问题【闭包的优点】
	2.1 内部函数可以访问到外部函数的局部变量
	2.2 闭包可以解决的问题
	  var lis = document.getElementsByTagName('li');
      for(var i=0;i<lis.length;i++){
        (function(i){                //内部函数可以访问到外部函数的i
          lis[i].onclick = function(){
            alert(i);                
          }
        })(i)
      }
3. 闭包的缺点
	3.1 变量会驻留在内存中,造成内存损耗问题。
				解决:把闭包的函数设置为null    //lis[i] = null
  3.2 内存泄漏【ie】 ==> 可说可不说,如果说一定要提到ie

image-20230114093406689

原型链(最高频)

1.原型可以解决什么问题

解决了共享属性和方法的问题 (new不能共享属性和方法)

2.谁有原型

函数有显示原型 prototype
对象有隐式原型 __proto__
  1. 对象查找属性或者方法的顺序 先在对象本身查找 --> 对象的构造函数中查找 --> 对象的原型 --> 构造函数的原型中 --> 当前原型的原型中查找
  2. 原型链 4.1 是什么:就是把原型串联起来 4.2 原型链的最顶端是null

JS继承有哪些方式

方式一: extends

class Parent{
	constructor(){
		this.age = 18;
	}
}

class Child extends Parent{
	constructor(){
		super();
		this.name = '张三';
	}
}
let o1 = new Child();
console.log( o1,o1.name,o1.age );

方式二: 原型链继承

function Parent(){
	this.age = 20;
}
function Child(){
	this.name = '张三'
}
Child.prototype = new Parent();   //子类原型指向父类实例
let o2 = new Child();
console.log( o2,o2.name,o2.age );

方式三: 借用构造函数继承

function Parent(){
	this.age = 22;
}
function Child(){
	this.name = '张三'
	Parent.call(this);
}
let o3 = new Child();
console.log( o3,o3.name,o3.age );

方式四:组合式继承

function Parent(){
	this.age = 100;
}
function Child(){
	Parent.call(this);
	this.name = '张三'
}
Child.prototype = new Parent();
let o4 = new Child();
console.log( o4,o4.name,o4.age );

说一下call、apply、bind区别

共同点: 可以改变函数体this指向

语法: 函数.call()、函数.apply()、函数.bind()

区别:

1.bind不会立即执行

2.apply第二个参数必须是数组

1. call、apply可以立即执行。bind不会立即执行,因为bind返回的是一个函数需要加入() 执行。
2. 参数不同:apply第二个参数必须是数组。call和bind有多个参数需要挨个写。

场景

可说可不说
1. 用apply的情况
var arr1 = [1,2,4,5,7,3,321];
console.log( Math.max.apply(null,arr1) )  

2. 用bind的情况
var btn = document.getElementById('btn');
var h1s = document.getElementById('h1s');
btn.onclick = function(){
	console.log( this.id );
}.bind(h1s) 

sort背后原理是什么?

1.没有参数时候,按照字符编码排序

image-20230114103434728

2.有参数时候
arr.sort(function(a,b)){
	return a-b;   //从大到小排序
	return b-a;   //从小到大排序
}

3.参数是对象

image-20230114103736093

sort原理:
V8 引擎 sort 函数只给出了两种排序 InsertionSort 和 QuickSort,数量小于10的数组使用 InsertionSort,比10大的数组则使用 QuickSort。

之前的版本是:插入排序和快排,现在是冒泡

原理实现链接:https://github.com/v8/v8/blob/ad82a40509c5b5b4680d4299c8f08d6c6d31af3c/src/js/array.js

***710行代码开始***

深拷贝和浅拷贝

共同点: 复制

区别:

浅拷贝: 两人共用一个地址(只复制引用,而未复制真正的值)

image-20230114104207681

深拷贝 是两个不同地址(是复制真正的值 (不同引用))

image-20230114104633107

1. 浅拷贝:只复制引用,而未复制真正的值。
var arr1 = ['a','b','c','d'];
var arr2 = arr1;  //浅拷贝

var obj1 = {a:1,b:2}
var obj2 = Object.assign(obj1);

2. 深拷贝:是复制真正的值 (不同引用)
var obj3 = {
	a:1,
	b:2
}
var obj4 = JSON.parse(JSON.stringify( obj3 ));
obj3.a = '100';
obj4.b = '你怎么样';
console.log(obj3,obj4);  

//递归的形式实现深拷贝
function copyObj( obj ){
    //判断是不是数组
	if(  Array.isArray(obj)  ){
		var newObj = [];
	}else{
		var newObj = {};
	}
	//里面元素是对象或者数组
	for( var key in obj ){
		if( typeof obj[key] == 'object' ){
			newObj[key] = copyObj(obj[key]);
		}else{
			newObj[key] = obj[key];
		}
	}
	return newObj;
}
console.log(  copyObj(obj5)  );

localstorage、sessionstorage、cookie的区别

公共点:在客户端存放数据 区别:

  1. 数据存放有效期 sessionStorage : 仅在当前浏览器窗口关闭之前有效。【关闭浏览器就没了】 localStorage : 始终有效,窗口或者浏览器关闭也一直保存,所以叫持久化存储。 cookie : 只在设置的cookie过期时间之前有效,即使窗口或者浏览器关闭也有效。

  2. localStorage、sessionStorage不可以设置过期时间 cookie 有过期时间,可以设置过期(把时间调整到之前的时间,就过期了)

  3. 存储大小的限制 cookie存储量不能超过4k localStorage、sessionStorage不能超过5M

    ****根据不同的浏览器存储的大小是不同的。

var、let、const区别(高频)

共同点: var,let,const都是可以声明变量

不同点:

1.变量提升

var有变量提升, let和const没有变量提升

2.多次声明

var可以多次声明, let和const多次声明会报错

3.赋值

var,let是变量,const是常量 不可以再次赋值

//注意const声明的对象里的属性可以改

4.作用域

var声明的变量没有自身作用域 ​ let和const声明的变量有自身的作用域

let和const只在块级作用域生效,var是全局变量

作用域考题

考题一:let和const没有变量提升性

```
console.log( str );//undefined
var str = '你好';

console.log( num );//报错,let和const没有变量提升性
let num = 10;
```

考题二:

```
function demo(){
	var n = 2;
	if( true ){
		var n = 1;   //var没有自身作用域
	}
	console.log( n );//1
}
demo();


function demo(){
	let n = 2;
	if( true ){
		let n = 1;   //1只在自身作用域生效
	}
	console.log( n );//2,
}
demo();
```

考题三:可以修改

```
const obj = {
	a:1
}
obj.a = 11111;   //可以修改,const对象的属性值可以修改
console.log( obj )

const arr = ['a','b','c'];
arr[0]= 'aaaaa';
console.log( arr );
```

将下列对象进行合并

题目:用你知道的方法合并下列对象
const a={a:1,b:4 }
const b={b:2,c:3 }

方式一:Object.assign

```
const a = {a:1,b:4};
const b = {b:2,c:3};

let obj1 = Object.assign(a,b);  //Object.assign合并对象
console.log( obj1 );  //{a:1,b:2,c:3}
```

方式二:...扩展运算符
扩展运算符(...)是ES6的语法,用于取出参数对象的所有可遍历属性,然后拷贝到当前对象之中

```
let obj2 = {...a,...b};
console.log( obj2 );
```

方式三:自己封装方法

```
function extend( target,  source ){
	for(var key in source){
		target[key] = source[key];
	}
	return target;
}
console.log( extend(a,b) );
```

箭头函数和普通函数有什么区别?(高频)

  1. this指向的问题 箭头函数中的this只在箭头函数定义时就决定的,而且不可修改的(call、apply、bind) 箭头函数的this指向定义时候、外层第一个普通函数的this

普通函数this指向的是它的直接调用者

2.箭头函数不能new(不能当作构造函数)

3.箭头函数没有prototype原型

4.箭头函数没有arguments对象

Promise相关

小厂: promise几种状态 + promise解决什么问题 + async/await

1.promise几种状态

pending(进行中)
fulfilled(已成功)
rejected(已失败)

2.promise解决什么问题

解决回调地狱问题,可读性和维护性差

3.async/await

比promise和generator代码简洁

image-20230114152903010

find和filter的区别

共同点: 返回新的数据,不改变原数组

区别一: 返回内容不同

find 返回具体的内容

filter 返回的是数组

区别二: 返回时机不同

find :匹配到第一个即返回 (找到就后面不看了) ​ filter : 返回整体(每一个匹配到的都返回)

some和every的区别(大厂)

some ==》 如果有一项匹配则返回true every ==》 全部匹配才会返回true

必考:ES 6 语法知道哪些,分别怎么用?

必考 Promise、Promise.all、Promise.race 分别怎么用?

必考:手写函数防抖和函数节流

如何实现类?

必考:立即执行函数是什么?

必考:什么是 JSONP,什么是 CORS,什么是跨域?

常考:async/await 怎么用,如何捕获异常?

常考:如何用正则实现 trim()?

常考:不用 class 如何实现继承?用 class 又如何实现?

手写系列

手写节流和防抖

手写发布订阅

必考:手写AJAX

手写简化版 promise

手写promise.all

阻止默认事件

阻止事件冒泡

数组常用方法

字符串操作方法

怎么判断数字是不是素数

promise捕获错误几种方式

异步任务有哪些

点击高亮选项卡和图标跟随鼠标移动实现(pink)

4. Vue2+3面试题

Vue2.x 生命周期有哪些?

Vue生命周期都有哪些?

完整解答过程:

1.系统自带了八个生命周期,分别是: 
  beforeCreate
  created
  beforeMount
  mounted
  beforeUpdate
  updated
  beforeDestroy
  destroyed
2.一旦进入组件或者一旦进入页面会执行之前前面4个 
  beforeCreate
  created
  beforeMount
  mounted
3. 如果使用了keep-alive会多出来两个生命周期
  activated
  deactivated
4.如果使用了keep-alive第一次进入组件会执行5个生命周期 
  beforeCreate
  created
  beforeMount
  mounted
  activated
5.如果使用了keep-alive第二次或者第N次,每次都会执行一个生命周期
  activated

额外附加知识:

在哪个阶段有el,在哪个阶段有el,在哪个阶段有data

$el :是 用于获取组件内 DOM

beforeCreate 啥也没有
created 开始有$data
beforeMount 同上
mounted 都有了(开始有$el)

谈谈对keep-alive了解?

1.keep-alive是什么

是vue自带的一个组件,功能:是用来缓存组件的 ===> 提升性能

  1. 使用场景

就是用来缓存组件,提升项目性能。避免多次重复请求

具体实现: 比如当用户从首页进入详情页,如果用户在首页每次点击都是相同的,

那么如果不用keep-alive,就会重复请求相同页面,

因此直接用keep-alive 缓存起来就行,避免多次重复请求

如果点击的不是同一个页面,就直接请求

v-show和v-if是干什么?有什么区别?

image-20230114163643647

使用场景:

v-show :加入购物车、分享、蒙层这种都基本上用v-show ​ v-if : 首页栏目切换的时候v-if

2.1 v-show

显示和隐藏 : display:none进行隐藏 、display:block进行显示		

2.2 v-if

创建和删除:remove、append		

2.3 区别:

显示和隐藏用:v-show
创建和删除用:v-if

频繁切换用:v-show
不频繁切换用:v-if	

首次加载:用v-if,不用v-show
为什么:
			如果用v-if可以没有这个盒子,然后再通过v-if进行创建(但是第一次进入页面是没有这个盒子,是不加载的)。
			如果用v-show这个盒子不管是显示还是隐藏,该盒子都是在的(节点都是存在)

v-if和v-for优先级(缺)

v-for的优先级要比v-if的优先级高

证明这个事情,是在vue.js源码种10997行

if (el.staticRoot && !el.staticProcessed) {
  return genStatic(el, state)
} else if (el.once && !el.onceProcessed) {
  return genOnce(el, state)
} else if (el.for && !el.forProcessed) {
  return genFor(el, state)
} else if (el.if && !el.ifProcessed) {
  return genIf(el, state)
} else if (el.tag === 'template' && !el.slotTarget && !state.pre) {
  return genChildren(el, state) || 'void 0'
} else if (el.tag === 'slot') {
  return genSlot(el, state)
} else {
注:v-if和v-for不要写在同一个节点上,这个性能很差。(v-if要写在父节点上)

ref是什么?

ref是什么?

获取dom

ref使用场景?

如果项目中使用插件,并且插件是要获取dom的,那么就可以使用ref了。

nextTick是什么?

nextTick是什么?

当dom更新完毕执行内部代码

使用场景:

插件要获取更新后的dom,例如swiper要获取从服务器请求回来的轮播图片

image-20230114164936381

scoped原理

  1. 作用: 让样式在本组件生效,不影响其他组件
  2. 原理: 就是给节点加上一个自定义属性,css根据属性选择器添加样式

Vue中如何做样式穿透

stylus样式穿透使用: >>> sass和less使用: /deep/ 通用使用: :v-deep

image-20230114171250330

image-20230114171240292

组件通信

父传子

父传子 props

image-20230114171742890

子传父

子传父 自定义事件 $emit

image-20230114171806102

兄弟组件间

兄弟间 全局事件总线bus.on,bus.on,bus.emit

image-20230114171839620

computed、methods、watch有什么区别?

  1. computed vs methods区别 computed是有缓存的 (多次使用同一个计算属性,只会用第一个的缓存) methods没有缓存
  2. computed vs watch区别 watch是监听,数据或者路由发生了改变才可以响应(执行) computed计算某一个属性的改变,如果某一个值改变了,计算属性会监听到进行返回 watch是当前监听到数据改变了,才会执行内部代码

一句话: watch强调的是监听的数据/路由 computed强调的是计算的属性

props和data优先级谁高?

优先级 props > data

具体在源码里

vuex相关

vuex是状态管理模式

vuex有哪些属性

state、getters、mutations、actions、modules

state 类似于组件中data,存放数据 getters 类型于组件中computed mutations 类似于组件中methods actions 提交mutations的 modules 把以上4个属性再细分,让仓库更好管理

vuex是单向还是双向数据流

Vuex是单向数据流

vuex中mutaions 和 actions 区别

mutaitons : 都是同步事物 actions : 可以包含任意异步操作,

action提交的是mutation,而不是直接改变状态

***在调试中就看出来

vuex如何做持久化存储

Vuex本身不是持久化存储

  1. 使用localStorage自己写
  2. 使用vuex-persist插件

解决跨域问题

?

vue设置代理

image-20230114174425061

image-20230114174459521

slot插槽

使用场景: 组件中有些地方布局可能大多都一致,但是细微有些小变化

Vue路由模式

两种路由模式:historyhash
区别:
	1. 表现形态不同
			history:http://localhost:8080/about
			hash:http://localhost:8080/#/about
	2. 跳转请求(路径改变时候)
			history : http://localhost:8080/id   ===>(404找不到时候)发送请求
			hash 	  : 不会发送请求
	3. 打包后前端自测要使用hash,如果使用history会出现空白页

介绍一下SPA以及SPA有什么缺点?

SPA是什么Single Page WebApplication?单页面应用 缺点:

1. SEO优化不好
2. 性能不是特别好

vue路径传值

1. 显式:通过query
	http://localhost:8080/about?a=1   //显示就是url上有显示
	 传:this.$router.push({
  			path:'/about',
  			query:{
  				a:1
  			}
  		})
   接:this.$route.query.a
  
2. 隐式:通过params
	http://localhost:8080/about
	传:this.$router.push({
  			name:'About',
  			params:{
  				a:1
  			}
  		})
    接:this.$route.params.a

路由导航守卫有哪些?

三种路由导航守卫:全局、路由独享、组件内

  1. 全局 beforeEach、beforeResolve、afterEach
  2. 路由独享 beforeEnter
  3. 组件内 beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave

使用场景:判断是否登录,如果登录就next否则就跳转到登录页面

vue动态路由

场景:详情页(文章、商品)
router.js配置:
	{
    path: "/list",
    name: "List",
    children:[
      {
        path:"/list/:id",     // /list/id  就会跳转到这个路由
        name:'Details',
        component: () =>
          import("../views/Details.vue"),
      }
    ],
    component: () =>
      import("../views/List.vue"),
  },

v-model双向绑定原理

通过Object.defineProperty劫持数据发生的改变,如果数据发生改变了(在set中进行赋值的),触发update方法进行更新节点内容({{ str }}),从而实现了数据双向绑定的原理。

diff算法

太难了,不会

Vue双向绑定和单向绑定

讲一下MVVM框架

web1.0时代

文件全在一起,也就是前端和后端的代码全在一起

问题:

1、前端和后端都是一个人开发。(技术没有侧重点或者责任不够细分)

2、项目不好维护。

3、html、css、js页面的静态内容没有,后端是没办法工作的(没办法套数据)。

mvc....都是后端先出的

web2.0时代

ajax出现了,就可以:前端和后端数据分离了。

解决问题:后端不用等前端页面弄完没,后端做后端的事情(写接口)、前端布局、特效、发送请求。

问题:

1、html、css、js都在一个页面中,单个页面可能内容也是比较多的(也会出现不好维护的情况)。

出现前端的框架了MVC、MVVM

解决问题:可以把一个“特别大”页面,进行拆分(组件化),单个组件进行维护

什么是MVVM

Model-View-的简写

image-20230115083416075

view : 视图【dom==》在页面中展示的内容

model:模型【数据层:vue中的data数据

viewModel:视图模型层【就是vue源码

页面中的内容是通过data展示的

比如说一个str字符串,通过vue源码,把str解析为真正的数据,数据发生改变时候就改变model的数据,从而更新view视图层

image-20230115084031778

必考:Vue 有哪些生命周期钩子函数?分别有什么用?

必考:Vue 数据响应式怎么做到的?

必考:Vue.set 是做什么用的?

Vue2如何实现双向绑定?

Vue3 为什么要用Proxy?

Vue3 为什么要用Composition API?

Vue3 对比 Vue2 有什么改动

说一下自定义指令

路由传参?

5. 其他

HTTP

必考:HTTP 状态码知道哪些?分别什么意思?

大公司必考:HTTP 缓存有哪几种?

必考:GET 和 POST 的区别

Cookie V.S. LocalStorage V.S. SessionStorage V.S. Session

http和https区别

http/1.1 和http/2区别

tcp三次握手和四次握手

安全

必考:什么是 XSS?如何预防?

必考:什么是 CSRF?如何预防?

SQL注入

接口安全

Webpack

必考:有哪些常见 loader 和 plugin,你用过哪些?

英语题:loader 和 plugin 的区别是什么?

必考:如何按需加载代码?

必考:如何提高构建速度?

转义出的文件过大怎么办?

上面五题请看这个不错的参考:zhuanlan.zhihu.com/p/44438844

webpack插件

微信小程序面试题

面试题:如何自定义头部?

面试题:如何自定义底部?

Git面试题

面试题:git常用命令

面试题:解决冲突

面试题:GitFlow

微信小程序面试题

面试题:如何自定义头部?

面试题:如何自定义底部?

token

SEO

面试题性能优化篇

加载优化

图片优化

渲染优化

首屏优化

vue优化

前端怎么给数据加密