前端面试题--三剑客篇(持续更新中)

发布时间:2024年01月01日

js css html 部分

1.forEach和map的区别
1.forEach方法是遍历数组里面的每一个元素,该方法没有返回值,仅用于执行副作用(如修改数组)
2.map方法也是遍历数组的每一个元素,并且传入一个回调函数,和forEach不同,它会返回一个新的数组,该数组是原数组处理计算后的值
3.虽然 forEach 和 map 都可以对数组进行遍历,但二者的返回值不同。如果需要对数组进行修改或其他副作用操作,使用 forEach 更为合适;如果需要得到一个新的数组,其中的元素是原数组经过某种变换后的结果,使用 map 更为合适。
2.for in 和for of的区别
1.for...in 语句用于遍历一个对象的可枚举属性(包括继承而来的属性),按照属性名的顺序进行迭代,通常用于遍历对象。
2.for...of 语句用于遍历具有 Iterable 接口的数据结构(如数组、字符串、Set、Map 等),会迭代这些数据结构中的每个元素,并返回当前元素的值,通常用于遍历数组和字符串。
3.虽然 for...in 和 for...of 都可以用于遍历数据结构,但它们之间还是存在一些显著的区别。for...in 循环的是对象的属性,不适合遍历数组和字符串等类数组的数据结构,而 for...of 可以遍历具有迭代器接口的数据结构中的元素。另外,for...in 遍历对象时,返回的是属性名,而不是属性值,因此还需要通过对象访问属性值;而 for...of 直接返回数组或字符串中的元素值,更为方便。
3.谈谈你对eventloop的理解
定义:异步js执行的机制,eventloop就是解决异步问题的
    
原理:主要的执行方式是:在js中,代码刚刚执行的时候,会判断代码是同步还是异步,
如果代码是同步的话,代码会直接进入调用栈执行,等待调用栈执行完成后,就会开启eventloop.
如果在判断的时候,是异步的话,代码会被放在webapi中等待时机执行,等待时机成熟之后,
会进入taskqueue中等待同步的代码完成,当同步的代码完成,如果异步的代码还没有完成的话,
eventloop就会每隔一段时间访问异步的taskqueue中,如果taskqueue中有等待的代码,
就会将代码按照同步的方式执行,放到调用栈中,循环此过程,直到所有的代码完成

异步的执行方式还分为:宏任务和微任务,如果是异步的宏任务,会直接进去webapi的队列,
随后进入task queue任务队列,如果是异步的微任务,会进入,micro taskqueue进行等待
,eventloop会优先执行微任务的micro taskqueue的队列,

1.webp

4.谈谈你对BFC的理解
BFC
英文名称block formating context   中文名称块级格式化上下文
如果某个元素符合bfc的规则时,该元素会形成一个独立的布局空间,在该空间的子元素不会受到外部布局的影响
也不会影响外部的布局,如果有margin.和高度塌陷问题,就可以触发bfc来解决.
开启bfc的方式有 1.给父元素添加浮动right和浮动left
	          2.设置positionabsoluate,relative,fixed
	          3.overflow:auto,hidden
	          4.display:inline-block
5.★谈谈你对闭包、变量污染、作用域、作用域链的理解
闭包:
    什么是闭包?
        闭包简单来说就是访问函数内部定义的变量.
    
    为什么要使用闭包?
        闭包的使用场景是因为,有的变量在函数内部无法访问到,如果将变量放在函数的外部,就会造成变量污染.

    什么是变量污染?
        变量污染就是,在外部声明的变量,如果函数内部没有声明变量的话,就会根据作用域链的访问规则,
        向父级寻找声明,找到声明后在使用变量,这样的话,在第二次调用函数的时候,就会造成变量的污染,
        假设函数内部是一个自加的函数,那么第二调用的时候,会将上一次的和拿过来当做初始值,进行计算,
        如果函数内部有个字符串,那么就会造成字符串拼接.

    解决变量污染问题:
        使用闭包,实现变量私有化,访问局部作用域,不会造成变量污染.

    闭包的语法:
        function getSum(){
            let a = 1
            return function(){
                console.log(a)
            }
        }
        let Sum = getSum()  //这句话的意思是调用函数==>getSum()返回的就是后面return的函数
        Sum()             //调用上面返回的函数  根据下方的作用域链的访问规则,返回的函数,会自动寻找上一级的变量
    
    作用域:
    函数和变量能够访问的区域,就叫作用域
    一般分为三种,第一种是全局作用域,第二种是函数作用域,第三种是块级作用域.

    作用域链:
    如果函数层层嵌套的话,在函数额内部有一个变量没有声明,它就会找它的上一层,如果上一层没有的话,就会继续往上找,直到找到为之,如果没有找到的话,就会显示变量没有被定义,例如:
      function box(){
            function box2(){
                function box3(){
                    a = 10          //如果这一行注释,就显示a没有被定义
                    function box4(){
                        a++
                        console.log(a);
                    }
                    box4()
                }
                box3()
            }
            box2()
        }
        box()

    闭包的优点:
        闭包可以实现变量的私有性,可以访问到函数内部的声明的变量
        在适当的时候,可以在内存中维护变量并缓存,提高执行效率

    闭包的缺点:
        通常来说,函数的活动对象会随着上下文环境一起被销毁,但是由于闭包引用的是外部函数的活动对象,因此这个活动对象无法被销毁,因为闭包比一般函数消耗更多内存.
6.★ES6有哪些新特性?
1.let和const变量声明 
2.箭头函数表达式 
3.类声明 
4.模板字面量字符串 
5.解构赋值 
6.扩展操作符 
7.迭代器和生成器 
8.Promise异步编程 
9.for...of循环 
10.Symbol类型和Symbol属性 
11.Map和Set数据结构 
12.默认参数 
13.Rest参数 
14.可计算属性名称 
15.模块化导出和导入
7.http和https的区别
1.HTTP (Hypertext Transfer Protocol) 是一种用于在 Web 浏览器和 Web 服务器之间传输数据的协议,它使用明文传输数据。
2.HTTPS (HTTP Secure) 是 HTTP 协议的安全版本,它通过使用 SSL/TLS 加密技术来保护数据传输安全。 HTTPS 使用加密算法对数据进行加密,使得攻击者无法窃取或篡改数据,同时也可以验证服务器的身份,确保通信双方的真实性。

因此,HTTP 和 HTTPS 最主要的区别在于安全性:HTTP 不安全,而 HTTPS 是安全的。当涉及到敏感信息(例如银行账户或密码)时,建议使用 HTTPS,以确保数据的保密性和完整性
8.js遍历对象的方法有哪些?
 1.for...in 循环:用于枚举对象的可枚举属性,包括继承自原型链上的属性。
 2.Object.keys() 方法:返回对象自身的所有可枚举属性的键名数组。
 3.Object.values() 方法:返回对象自身的所有可枚举属性的值数组。
 4.Object.entries() 方法:返回对象自身的所有可枚举属性的键值对数组。
 5.Object.getOwnPropertyNames() 方法:返回对象自身的所有属性(包括不可枚举属性)的键名数组。
 6.Reflect.ownKeys() 方法:返回对象自身的所有键名数组,包括可枚举和不可枚举属性以及 Symbol 类型的键。
9.★谈谈你对promise的理解
promise是ES6的重要特性之一,传统的异步编程的解决方案是回调函数,这样会循环嵌套,造成回调地狱的问题,promise是另一种解决异步编程的方法.

三种状态:
pending(待定)初始状态,既没有被兑现,也没有被拒绝
fulfilled(成功)意味着操作成功完成
rejected(失败)意味着操作失败

promise的三个实例方法:
then
catch
finally()
promise.then(result => {···}).catch(error => {···}).finally(() => {···});

promise的静态方法:
resolve方法

reject()方法
Promise.reject(reason)方法也会返回一个新的 Promise 实例,该实例的状态为rejected(失败)

any()方法
只要其中的一个 promise 成功,就返回那个已经成功的 promise 。如果对象中没有一个成功,那就会返回一个失败的promise实例

All()方法
const p = Promise.all([p1, p2, p3]);
所有的都成功才会成功,否则就会失败

allSettled方法
Promise.allSettled() 静态方法会等待所有源 Promise 进入 fulfilled 或者 rejected 状态,从而确保不会造成时序上的冲突

race方法
将多个 Promise 实例,包装成一个新的 Promise 实例,p1、p2、p3之中有一个实例先改变状态,p的状态就跟着改变
const p = Promise.race([p1, p2, p3]);

ESES8中新增了Promise的语法糖async await来更优雅的处理异步
async 可以单独存在, 用该关键字声明的函数返回的是一个 Promise 对象
await 不可以单独存在,必须要配合 async 一起存在使用
两者配合使用,可以使异步处理的更优雅


promise的缺点:
1、无法取消Promise,一旦新建它就会立即执行,无法中途取消。
2、如果不设置回调函数,promise内部抛出的错误,不会反应到外部。
3、当处于pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。
10.ajax的请求流程
1.建立XMLHttpRequest对象;
2.设置回调函数;
3.配置请求信息,(如open,get方法),使用open方法与服务器建立链接;
4.向服务器发送数据;
5.在回调函数中针对不同的响应状态进行处理;
11.h5新增的特性
Canvas、SVG -- 用于绘画的元素,canvas绘制的图片会失真而SVG绘制的不会失真。
video、audio -- 用于播放视频和音频的媒体。
Drag 、Drop -- 用于拖放的 。
Geolocation -- 用于获取地理位置。
localStorage、sessionStorage -- 用于本地离线存储。
webSQL、IndexDB -- 前端数据库操作,由于安全性极低,目前h5已放弃。
web Worker -- 独立于其他脚本,不影响页面性能运行在后台的javascript。
webSocket -- 单个TCP连接上进行全双工通讯的协议。
新的特殊内容元素 -- 如:article、footer、header、nav、section。
新的表单控件 -- 如:date、time、email、url、search。
12.cs3新增的特性
新增选择器 p:nth-child(n){color: rgba(255, 0, 0, 0.75)}
弹性盒模型 display: flex;
多列布局 column-count: 5;
媒体查询 @media (max-width: 480px) {.box: {column-count: 1;}}
个性化字体 @font-face{font-family:BorderWeb;src:url(BORDERW0.eot);}
颜色透明度 color: rgba(255, 0, 0, 0.75);
圆角 border-radius: 5px;
渐变 background:linear-gradient(red, green, blue);
阴影 box-shadow:3px 3px 3px rgba(0, 64, 128, 0.3);
倒影 box-reflect: below 2px;
文字装饰 text-stroke-color: red;
文字溢出 text-overflow:ellipsis;
背景效果 background-size: 100px 100px;
边框效果 border-image:url(bt_blue.png) 0 10;
13.重排(回流)和重绘
1.重排(回流):简单来说,就是当我们对 DOM 结构的修改引发 DOM 几何尺寸变化的时候,会发生重排的过程.
2.重绘:当 DOM 的修改导致了样式的变化,并且没有影响几何属性的时候,会导致重绘(repaint)
注意:回流 (重排)必将引起 重绘 ,但 重绘 不一定会引起 回流 (重排)。
14.★ES5的继承
第一种 通过原型链继承
// 父类
function SuperType() {
    this.colors = ['red', 'blue', 'green']
}
// 子类
function SubType() { }
SubType.prototype = new SuperType()

let instance1 = new SubType()
instance1.colors.push('black')
console.log(instance1.colors)  // "red,blue,green,black"

let instance2 = new SubType()
console.log(instance2.colors)  // "red,blue,green,black"
缺点如下:
 *1》原型中包含的引用值会在所有实例之间共享,修改一个实例,另一个实例会跟着修改
 *  即:通过将属性定义在构造函数中
 *2》子类实例化时,无法给父类构造函数传参


第二种方式 通过构造函数继承
// 父类
function SuperType(name) {
    this.name = name
}
// 子类
function SubType(name1) {
    SuperType.call(this, name1)
    this.age = 28
}
let instance1 = new SubType('测试名称')
console.log(instance1.name) // 测试名称
console.log(instance1.age) // 28

 * 缺点如下:
 *1》必须在构造函数中定义方法,因此函数不能复用
 *2》子类不能访问父类原型上定义的方法
 * 为确保 SuperType 构造函数不会覆盖 SubType 定义的属性,
 * 可以在调用父类构造函数之后再给子类实例添加额外的属性


第三种方式 使用组合式继承
15.ES6继承
        //父类
		class Parent{
            constructor(a, b){
                this.a = a
                this.b = b
            }
            aa(){
                console.log('aa方法')
            }
            bb(){
                console.log('bb方法')
            }
        }
		//子类
        class Son extends Parent{
            // 啥也没有
        }
        var s1 = new Son(1,2)
        console.log(s1)
   	 	console.log(s1.b)
        s1.aa()
        s1.bb()
16.判断一个空对象(数组)的方法
1.判断空对象
第一种方法(es6的写法)	
let obj= {};
Object.keys(obj).length === 0----------表示是空对象//返回true
第二种方法
let obj={};
console.log(JSON.stringify(obj)==="{}"); //返回true
第三种方法
let result=function(obj){
    for(let key in obj){
        return false;//若不为空,可遍历,返回false
    }
    return true;
}
console.log(result(obj));//返回true

2.判断空数组
let array1=[];
array1.length === 0;------表示是空数组
17.★原型链
当我们访问一个对象的属性时,如果这个对象内部不存在这个属性,那么他就会去prototype里找这个属性,这个prototype又会有自己的prototype,于是就这样一直找下去,也就是我们平时所说的原型链的概念。
18.js实现双向绑定
<body>
    <!-- oninput 事件在用户输入时触发。 -->
    <input type="text" id="ipt" value="" oninput="contentChange(this.value)">
    <h3 id="content"></h3>
</body>
 	// 获取元素
    var ipt = document.getElementById('ipt')
    var content = document.getElementById('content')
    // 声明一个data对象,专门用来存放数据
    var data = {};
    // 用来给对象动态添加属性 define:定义 Property:属性
    // Object.defineProperty(对象的名称, 属性的名称, 配置项)
    // 注意:属性的名称必须是字符串,否则会被当做变量使用,且会报未定义的错误。(xx is not defined.)
    // get代表定义msg时,给其赋值的数据
    // set代表当你拿到最新的值时,接下来要进行的操作
    Object.defineProperty(data, 'msg', {
        get: function () {
            return "hello world"
        },
        set: function (newVal) {
            content.innerHTML = newVal;
            ipt.value = newVal;
        }
    })
    // 将数据源的最初值,展示在页面上
    content.innerHTML = data.msg;
    ipt.value = data.msg;
    // 当输入的数据发生变化时,需要修改数据源data.msg
    function contentChange(val) {
        data.msg = val;
    }
19.防抖和节流
防抖是指 所谓防抖,就是指触发事件后 n 秒后才执行函数,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。
 
let num = 1;
 const content = document.getElementById('content');
 // 功能函数
 function count() {
  this.innerHTML = num++;
 };
content.onclick = debounce(count,1000);

// 防抖函数,非立即执行版本
 function debounce(func, wait) {
  let timeout;
  return function () {
    const context = this;
    const args = [...arguments];
    if (timeout) clearTimeout(timeout);
    timeout = setTimeout(() => {
      func.apply(context, args)
    }, wait);
  }
}


所谓节流,就是指连续触发事件但是在 n 秒中只执行一次函数。**节流会稀释函数的执行频率。
20.Ajax的轮询
Ajax 轮询(Ajax Polling)指的是客户端定期向服务器发送请求,来检查数据更新的状态,以获得最新的数据。这种方式可以通过 setInterval 等定时器函数来实现。在每个固定的时间间隔内,客户端向服务器发送一个 Ajax 请求,服务器返回数据,然后客户端再根据返回的数据更新页面中的内容。

使用 Ajax 轮询的好处是可以及时地获得最新的数据,但是它的缺点是会造成过多的请求和网络的拥塞,影响服务器的处理能力。在 Ajax 轮询的过程中,客户端不断向服务器发送请求,即使在没有更新的情况下也会浪费网络带宽和服务器资源,同时也会增加服务器的负载和延迟。

为了解决 Ajax 轮询带来的这些问题,出现了一种新的技术——长轮询(Long Polling)。长轮询是指客户端向服务器发送一个请求,服务器不会立即响应,而是等待事件的发生,当事件发生时,服务器会立即返回响应。客户端在接收到响应后,再次发送请求,以便下一次的轮询。

长轮询技术通过减少服务器和客户端之间的通信次数来提高性能,减少了网络带宽和服务器资源的浪费,同时还可以更快地响应事件,提高了性能和用户体验。
21.es6中的set和map的区别
ES6 中的 Set 和 Map 是两个非常实用的数据结构,它们分别有以下的特点和区别:
1. Set

Set 是一个值的集合,其中每个值只能出现一次。Set 中的值可以是基本类型的值或对象的引用,通过 Set 的实例方法可以方便地添加、删除、遍历、判断集合中是否包含某个值等操作。
Set 内部的值是无序的,并且不能索引,所以不能通过下标来访问。

2. Map

Map 是一种键值对的集合,其中每个值都有一个对应的键,同一个键只能对应一个值。Map 中的键可以是任意类型的值,包括基本类型的值和对象的引用。通过 Map 的实例方法可以方便地添加、删除、遍历、判断集合中是否包含某个键值对等操作。
Map 内部的键值对是有序的,并且可以通过键来索引和访问相应的值。

3. 区别

Set 和 Map 的主要区别在于值的存储方式和查找方式不同。Set 中的值只有一个元素,而 Map 中的值则是由 键值对(key-value pairs) 组合的。
Set 在实际应用中通常用于去重或者存储一些唯一的元素,而 Map 则通常用于存储需要与键值相关联的数据。
另外,Set 和 Map 的 API 也略有不同,具体的使用方式需要根据实际需求来选择哪种数据结构。
22.请你阐述一下对vue虚拟dom的理解
虚拟dom本质上就是一个普通的JS对象
{
tag: 'div',
props: {
  id: 'app'
},
chidren: [
  {
    tag: 'p',
    props: {
      className: 'text'
    },
    chidren: [],
    text: 'hello world!!!'
  }
]
}

上面的js虚拟对象生成的html是:
<div id="app">
    <p class="text">hello world!!!</p>
</div>


在vue中,每一个组件其实都会被vue编译成一个vNode(虚拟dom),每个组件都有一个render函数,每个render函数都会返回一个虚拟dom树,这也就意味着每个组件都对应一棵虚拟DOM

image-20210225140726003

23.常见的设计模式有哪些?
JavaScript 中的设计模式常用于提高代码的重用性、可维护性和可读性等。以下是常见的 JavaScript 设计模式:

单例模式(Singleton Pattern):确保只有一个实例被创建并提供全局访问点。在 JavaScript 中,可以使用对象字面量、命名空间等方式来实现单例模式。

工厂模式(Factory Pattern):通过抽象工厂和具体工厂的方式进行对象创建和管理,从而实现面向对象编程中的多态性和封装性。

观察者模式(Observer Pattern):建立对象之间的依赖关系,当被观察对象发生变化时,通知观察者进行状态的更新。

发布/订阅模式(Pub/Sub Pattern):发布者将事件推送到一个特定主题,订阅者从该主题中接收事件的通知,从而实现组件之间的松散耦合。

除了以上列出的常见设计模式之外,JavaScript 中还有许多其他的设计模式,包括适配器模式、桥接模式、命令模式、中介者模式、访问者模式、责任链模式等。熟练掌握设计模式的使用可以大大提高开发代码的效率和质量,从而更好地应对各种开发场景和需求。
24.如何将5变成5.00
var i = 1;
alert(i.toFixed(2));
25.new关键字的作用
1.创建一个空对象
2.将this指向这个对象
3.完成对象的赋值(执行构造函数中的代码)
4.自动帮我们return 这个对象
26.改变this指向问题call,apply,bind
作用:强制绑定this的指向
区别:
1.传参形式不一样
传参形式不一样, call() 方法接受的是参数列表,而 apply() 方法接受的是一个参数数组
fn.call(obj, 1, 2);     //this-->obj,fun传入参数 1,2
fn.apply(obj, [1, 2]);  //this-->obj,fun传入参数 1,2

性能:call 的性能更好,不过 lodash 里的源码当参数小于等于 3 时用 call,之后用 apply

2.返回值不一样
bind绑定完不会立即执行函数,而是将函数返回【当要为回调函数绑定this只能用bind】,call,apply指定this后立即执行
fn.bind(obj);  //需要调用
//---------------------
var fn2=fn.bind(obj);
fn2();
//--->等价于
fn.bind(obj)();
27. 浏览器缓存
1. 什么是浏览器缓存?
浏览器缓存是指浏览器在访问 Web 页面时将页面的一些部分存储在本地,以便以后再次访问该页面时可以更快地加载页面。

2. 浏览器缓存的优点是什么?
浏览器缓存可以提高页面的加载速度,减轻服务器的负担,降低数据传输量,节省用户的流量费用等。

3. 浏览器如何使用缓存?
浏览器在请求 Web 页面时会检查页面的缓存状态,如果缓存过期或者页面没有被缓存过,会重新从服务器请求页面。如果缓存未过期,会直接从本地缓存中加载页面。

4. 如何设置浏览器缓存?
可以通过设置 HTTP 响应头中的 Cache-Control 和 Expires 字段来控制浏览器缓存的行为,比如缓存的最长时间、是否允许缓存、是否强制刷新等。另外也可以使用 Web Storage API、Service Worker 等技术来控制缓存。

需要注意的是,虽然浏览器缓存可以提高网站的性能,但是如果缓存设置不当,可能会影响网站更新和用户体验。因此,在实际开发中需要根据具体情况合理设置缓存策略。
文章来源:https://blog.csdn.net/GAGGAAAAA/article/details/135286757
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。