前端面试八股文(最新版)

目录

一、基础(大概率不问)

1.如何理解HTML语义化的?

2.HTML5有哪些新标签

3. BFC是什么?

4. 如何实现垂直居中?

5. Css选择器的优先级如何确定?【背诵】

6. 如何清除浮动?

7.  var/ let  / const  区别

二、Js [基础概念]

7. JS 的数据类型有哪些?

8. 数组的方法有哪些?

9. 原型链是什么

10.  this的指向 

11. JS 的 new 做了什么【记忆】

12. JS 的立即执行函数是什么【概念题】

13. JS 的闭包是什么?怎么用?

14. JS 如何实现类?

15. JS 如何实现继承?

16. 判断数据类型的方法

17. 作用域和作用域链

18.事件流有三个阶段:

三、js 重点

1. 遍历数组

2.  排序方法

3. 数据去重

4. 深浅拷贝


一、基础(大概率不问)

1.如何理解HTML语义化的?

    语义化标签时写html标签的一种方法论。

    段落要写成p标签,标题我会用h1-h6之间,文章呢用article,那么时间我会用time标签,画板会用kawasi标签。

优点:适合搜索引擎来检索,适合人类阅读利于团队维护

2.HTML5有哪些新标签

回答:平常用的就是header、atikou

延伸问题:Canvas 和SVG的区别?

  1. Canvas 主要是用笔刷来绘制 2D 图形的;
  2. SVG 主要是用标签来绘制不规则矢量图的;
  3. 相同点:都是主要用来画 2D 图形的,也可以绘制3D不常用;
  4. 不同点:Canvas 画的是位图,SVG 画的是矢量图;
  5. SVG 它是一个个的节点,在SVG里面画一个圆是一个节点,画一个正方形是一个节点,节点多了必然会卡,那渲染的就肯定比较慢了,canvas他没有节点,所以他的渲染性能从理论上说是比较好的,但就是写的比较复杂;
  6. 还有就是SVG 支持分层和事件,Canvas 不支持,但是可以用库实现。

3. BFC是什么?

  • 没有标准的话来定义,是块级格式化上下文。
  • 一般来说用条件来触发他,
  • 浮动,如果这个元素浮动了那这个元素就是BFC;
  • 绝对定位,如果把这个元素定位了,这个元素就是BFC;
  • 行内块元素,如果把这个元素inline变为 inline block,这个元素就是BFC;
  • 如果你把他的overflow的值设置为hidden只要不是visible就是BFC;
  • 只要把display设置为flex或者inline-flex,那么他的子元素就是BFC。

延伸问题:解决了什么问题?

      不知道解决了什么根源上的问题,但是我知道可以用来清除浮动、防止margin合并(两个垂直方向上的div他的margin是会合并的,但是只要有一个div触发了BFC就不会合并了)

4. 如何实现垂直居中?

  注:如果外面的(父级)高度没有明确写出来,那么就写一句padding:10px 0;[上下都是10像素,就居中了]

 如果父级的宽度有明确设定:

  1. flex
  2. Table自带属性;
  3. div装成table;
  4. 100%高度的after before + inline block;
  5. margin-top:50%;
  6. translate:50%;
  7. absolute:margin auto。

5. Css选择器的优先级如何确定?【背诵】

      通配符是最低的。选择器越具体越优先;相同的优先级,后面的覆盖前面的;属性后面加了!import的优先级最高。

6. 如何清除浮动?

方法一:在父元素上加上.clearfix。

.clearfix:after{

    Content:’’;

    Display:block/table;

    Clear:both;

}

方法二: 在父元素上添加overflow:hidden

7.  var/ let  / const  区别

  1. var 申明的函数作用域,let const 是块级作用域
  2. var 存在变量提升,let const 不存在
  3. var 允许重复申明,let const 不允许
  4. let 申明变量,const 声明常量
  5. let const 存在暂时性死区

二、Js [基础概念]

一个函数没有返回值和他返回undefined没办法区别

7. JS 的数据类型有哪些?

[8种]String、number、boolean、undefined、null、object、symbol、bigint

延伸问题:

1. 如果表示对象为空用null,如果表示非对象为空用undefined。

2. 为什么需要bigint? js的number它默认的是双精度浮点数,保存的位数是有限的,bigint 没有限,如果你这个数字特别大又想全部展现出来,由于js本身的number支持不了这个长有效位数的整数,这时候就用bigint。

3. 数组、函数、日期这三个是类,不是类型!

8. 数组的方法有哪些?

  1.  push  向数组的末尾添加一个或多个,并返回新数组
  2.  splice 删除或添加数组中的元素(我一般是用于删除的)
  3.  includes:判断数组中是否包含某个值
  4.  map 遍历数组
  5.  forEach 遍历数组

ps:详情请转至 js 数组的方法_乐~~~的博客-CSDN博客

9. 原型链是什么

  原型链涉及到的概念是比较多的,我先举例说一下,假设有一个普通对象x,x会有一个隐藏属性,这个属性会指向一个对象,这个对象叫object.prototype,因此得到一个公式,x的隐藏属性=object.prototype,这时候我们就说x的原型是object.prototype。

    假设有一个数组对象a[],它也有隐藏属性叫___???___,这个时候呢a的隐藏属性正好等于Array.ptototype,可以说a的原型是Array.prototype,同时Array.prototype也有隐藏属性,Array.prototype的原型是object.prototype,由此呢就形成了两层原型,a的原型是Array.prototype,a的原型的原型是object.prototype,这样就形成了原型链条。

简说:a的原型是b,b的原型是c,原型链就是a    b    c。

a.__???__ = b,b.__???__=c

10.  this的指向 

在不同的场景中调用同一个函数,this的指向也有可能发生变化。

  • 箭头函数中的this 指向函数作用域所用的对象
  • 普通函数中,谁调用this就指向谁,如果没有调用,就指向window
  • 构造函数中的this是指向实例
  • 参考链接:JS中的this指向_Armin444的博客-CSDN博客

 案例1 : 这个里面的this指的就是obj这个方法

let obj={
   name:"测试",
   say:function(){
    name:"测试1",
    console.log(this.name);
  }
}

obj.say(); //测试

 案例2 :

  1. 函数的定义位置不影响其this指向,this指向只和调用函数的对象有关

  2. 多层嵌套的对象,内部方法的this指向离被调用函数最近的对象

let newObj={
  name:"测试2",
  say:function(){
    name:"测试3",
    console.log(this.name);
  }
  obj2:{
    name:"测试4",
    skill:function(){
      name:"测试5",
      console.log(this.name); //内部方法中的this 指的是调用函数最近的对象,所以这里指的是obj2
    }
  }
}

newObj.say(); //测试2
newObj.obj2.skill();//测试4 

11. JS 的 new 做了什么【记忆】

  1. 帮我创建临时对象/新对象(必做)
  2. 绑定原型【就是共有的属性】
  3. 帮我指定this=临时对象
  4. 执行构造函数
  5. 帮我返回临时对象(必做)

12. JS 的立即执行函数是什么【概念题】

声明一个匿名函数,这种做法,(执行的过程)立即执行他。

目的:通过它创建局部变量;兼容性好

写法:!function(){}()

  • (立即函数);  可以用括号把整个函数包起来
  • 可以只包函数
  • 函数前可以加!、~、+、- 、new、var

13. JS 的闭包是什么?怎么用?

        闭包是一种语法特性,js的所有函数都支持闭包,只要有函数+自由变量就是闭包,闭包不能用全局变量。【如果一个变量不是局部变量、不是全局变量,那么就是自由变量】

【缺点】:闭包使用不当,可能导致内存泄漏。

【讲解】:声明一个变量,它=一个立即执行函数,这个立即执行函数里面声明一个count,然后再声明一个函数对count进行操作。

【什么场景使用】优点:避免污染全局变量。提供对局部变量的间接访问。维持变量,使其不被垃圾回收。

【闭包形成的条件】:函数嵌套、内部函数引用外部函数

function fun(){
    var count = 1;
    function fun2(){//条件1:函数嵌套
    //形成条件2:内部函数引用外部函数
    console.log(count);
    }
}
fun();

14. JS 如何实现类?

1. 第一种呢是使用原型,我们把他们对象本身的属性写在构造函数里面,把共有的属性写在原型上面。

Function Dog(name){
 This.name=name;
This.legsNum=4;
}
Dog.prototype.say=function(){
 Console.log();
}
Dog.prototype.kind=’狗’
Const d1=new dog(“哈哈”);
D1.say();

2. 第二种是用class方法,吧对象本身的属性写在constructor里面,共有属性写在外面(没有办法申明在原型上面)。

Class Dog{
 Kind=”狗”;//相当于在controctor里面写this.kind
Constructor(name){
 This.name=name;
 This.legsNum=4;
}
Say(){
  Console.log(‘哈哈哈,我是${this.name}’);
}}
Const d1=new Dog(“小猴狗”);
D1.say()

3. class没有提供在原型上添加非函数属性的方法。

15. JS 如何实现继承?

自身属性要继承,共有属性要继承  

class Animal{

  constructor(legsNumber){ss

    this.legsNumber = legsNumber //animal本身的属性

  }

  run(){}

}

class Dog extends Animal{

  constructor(name) {

    super(4)

    this.name = name

  }   // run(){}

  say(){

    console.log(`汪汪汪~ 我是${this.name},我有${this.legsNumber}条腿。`)

  }

}

16. 判断数据类型的方法

1. typeof 

     返回的数据类型:string,number,boolean,symbol,bigint,unfined,object,function

 延伸问题:为什么typeof null 是 Object?

       因为在JavaScript中,不同的对象都是使用二进制存储的,如果二进制前三位都是0的话,系统会判断为是Object类型,而null的二进制全是0,自然也就判断为Object

2.instanceof  根据原型链判断

  • 判断引用数据类型的,判断基本数据类型无效

17. 作用域和作用域链

(1)作用域:

  • 全局作用域:变量,函数在整个全局中都能被访问到;
  • 局部作用域:函数,{}内部声明的变量和函数

(2)作用域链:

上下级之间的不同作用域构成作用域链。

  • 内部函数访问外部函数函数变量就是采取的是作用域链查找

18.事件流有三个阶段:

  • 事件捕获阶段:从window逐层向下传递到目标元素(父级到子级),过程中遇到注册的捕获事件就触发它;
  • 处于目标阶段:事件达到目标元素,触发目标元素上注册的事件
  • 事件冒泡阶段:从目标元素向上传递到window(子级到父级),过程中遇到注册的冒泡时间就会触发它

三、js 重点

1. 遍历数组

let test=[{
    "id":1,"name":"圣诞节佛"
},{
    "id":2,"name":"圣诞水电费节佛"
}]
test.forEach((element)=>{
    console.log(element);
}) 
let test=[{
    "id":1,"name":"圣诞节佛"
},{
    "id":2,"name":"圣诞水电费节佛"
}];
let tests=[];
test.map((element)=>{
    if(element.id==1){
        tests.push(element);
    }
});
console.log("1",test);
console.log("2",tests)

2.  排序方法

2.1 冒泡排序

<script>

data(){
 a:[1,23,456,67,78,34,567]
},
mounted(){
 this.init();
},
methods:{
 init(){
   this.maopaoSort(this.a);
   console.log(this.a); //[1,23,34,67,78,456,567]
 },

 sortt(arr){
    const len=arr.length;
    if(len<2){
        return arr;
    }else{
        for (let i = 0; i < len; i++) {
            for(let j=0;j<i;j++){
                if(arr[j]>arr[i]){
                    const temp=arr[j];
                    arr[j]=arr[i];
                    arr[i]=temp
                }
            }
        }
        return arr;
    }
 }
}

 

</script>

2.2 选择排序

let a = [1, 75,8,5,96];
 
function selectSort(array) {
  const len = array.length
  let temp
  let minIndex
  for (let i = 0; i < len - 1; i++) {
    minIndex = i
    for (let j = i + 1; j < len; j++) {
      if (array[j] <= array[minIndex]) {
        minIndex = j
      }
    }
    temp = array[i]
    array[i] = array[minIndex]
    array[minIndex] = temp
  }
  return array
}

selectSort(a);//[1,5,8,75,96]

3. 数据去重

3.1 set (*****必会) 

let a=[1,2,4,5,2,4,2,2,2,1,4,5,6,7,6];
let b=Array.from(new Set(a));
console.log(b)//[1, 2, 4, 5, 6, 7];

3.2  filter+includes

function test(params) {
    let newarr=[];
    newarr=params.filter(function (item) {
        return newarr.includes(item)?'':newarr.push(item);
    })
    return newarr;
}

console.log(test([1,1,5,5,84,22,45,88,55,7,5])); //[1, 5, 84, 22, 45, 88, 55, 7]

ps: 上面这俩种只能处理基本类型的数组,对于数组里面是对象的这种,就直接返回原值。

4. 深浅拷贝

浅拷贝:如果是基本类型,则拷贝的是基本类型的值(拷贝一层);如果是引用数据类型的话,就是拷贝地址。

深拷贝:不会只传地址,而是会开辟一个新的空间,然后复制到另一个空间。

浅拷贝方法:

      Object.assign(target,sources)  //target 你要拷贝给谁,这个就是人家的名字;sources 是被拷贝的那个。

let obj={
    id:1,
    name:'anya',
    msg:{
        age:18
    }
};
let o={};
Object.assign(o,obj);
o.msg.age=20; //浅拷贝,o里面的值变了,obj里面的值也会随之改变
console.log(o);
console.log(obj);

还有一种:扩展运算符

let arr=[1,1,2];
let newArr=[...arr];
console.log(newArr); //[1,1,2];
newArr[0]=22;
console.log(newArr);//[2,1,2]
console.log(arr);//[1,1,2]

深拷贝方法:JSON.stringigy();

let a=[1,2,3,{name:1,dsc:"sfj圣诞节佛了"}];
let b=JSON.stringify(a)
console.log(b) //[1,2,3,{name:1,dsc:"sfj圣诞节佛了"}];
b[3]=12;
console.log(a);//[1,2,3,{name:1,dsc:"sfj圣诞节佛了"}];

5. promise

利用promise可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。promise是同步的,then是异步的。promise必须实现then方法,then方法接收两个回调函数,他们分别是成功时的回调和失败时的回调。

promise 的三种状态:

promise的三种状态:

  •   pending 初始状态
  •   resolved 操作成功
  •   rejected 操作失败

promise 的方法

  • promise.all()
  • promise.reace()