前端面试题汇总(持续更新)-程序员宅基地

技术标签: css  前端  html  javascript  

一、CSS

1、说一下CSS的盒模型

在HTML页面中的所有元素都可以看成是一个盒子
盒子的组成:内容(content)、内边距(padding)、边框(border)、外边距(margin)
盒模型的类型:
标准盒模型:
margin + border + padding + content
IE盒模型:
margin + content( border + padding)
控制盒模型的模式:
box-sizing:content-box(默认值,标准盒模型) 、border-box(IE盒模型)

2、CSS选择器的优先级

CSS的特性:继承性、层叠性、优先级
优先级:写CSS样式的时候,会给同一个元素添加多个样式,此时谁的权重高就显示谁
标签选择器、类选择器/伪类选择器/属性选择器、全局选择器、行内样式、id选择器、!important
优先级:
!important > 行内样式 > id > 类选择器/伪类选择器/属性选择器 > 标签选择器 > 全局选择器

3、隐藏元素的方法有哪些

display: none;
元素在页面上消失,不占据空间
opacity: 0;
设置元素的透明度为0,元素不可见,占据空间位置
visibility: hidden;
让元素消失,占据空间位置,一种不可见的状态
position: absolute; 从当前位置踢出去
clip-path: 待隐藏的元素剪切掉

4、px和rem的区别是什么

px: 是像素,显示器上给我们呈现画面的像素,每个像素的大小是一样的,绝对单位长度
rem: rem 是所有 DOM 节点对于根节点 html 的相对值。
1、浏览器默认的字号是16px,因此如果没有设置根节点 html 的字号,这将会是一个默认基数
2、rem 与 px 的换算为 px = rem * 设置的根节点字号。

		1.设置了根节点 html 字体大小
			html{
    font-size:12px}
			div{
    width:4rem;}
			//div 的宽度换算为 px 为 4rem*12px = 48px
		2.没有设置根节点 html 字体大小
			div{
    width:4rem;}
			//div 的宽度换算为 px 为 4rem*16px = 64px
			注意,html 字体大小最小为 12px;如果设置为10px,则换算后的 px 依然按照 12px 计算
		3.设置根节点 html 字体大小小于12px
			html{
    font-size:10px}
			div{
    width:4rem;}
			//div 的宽度换算为 px 为 4rem*12px = 48px

5、重绘和重排有什么区别

重绘:重新绘制;计算好盒模型的位置大小和其他一些属性之后,浏览器就会根据每个盒模型的特性进行绘制
重排(回流):重新排列;布局引擎会根据所有的样式计算出盒模型在页面上的位置和大小
浏览器的渲染机制:
对DOM的大小、位置进行修改后,浏览器需要重新计算元素的这些几何属性,就叫重排
对DOM的样式进行修改,比如color和background-color,浏览器不需要重新计算几何属性的时候,直接绘制了该元素的新样式,那么这里就只触发了重绘

6、让一个元素水平垂直居中的方式有哪些

1、定位 + margin

<div class="father">
    <div class="son"></div>
</div>
<style>
*{
    
    margin: 0;
    padding: 0;
}
.father{
    
    width: 400px;
    height: 400px;
    border: 1px solid;
    // 父元素要加上相对定位
    position: relative;
}
.son{
    
    //子元素要加上绝对定位
    position:absolute;
    width:200px;
    heihgt:200px;
    background-color:red;
    top:0;
    right:0;
    bottom:0;
    left:0;
    margin: auto;
}
</style>
2、定位 + transform
<div class="father">
    <div class="son"></div>
</div>
<style>
*{
    
    margin: 0;
    padding: 0;
}
.father{
    
    width: 400px;
    height: 400px;
    border: 1px solid;
    // 父元素要加上相对定位
    position: relative;
}
.son{
    
    //子元素要加上绝对定位
    position:absolute;
    width:200px;
    heihgt:200px;
    background-color:blue;
    top:50%;
    left:50%;
    transform: translate(-50%,-50%)
}
</style>
3、flex布局
<div class="father">
    <div class="son"></div>
</div>
<style>
*{
    
    margin: 0;
    padding: 0;
}
.father{
    
    display:flex;
    justify-content:center;
    align-items:center
    width: 400px;
    height: 400px;
    border: 1px solid;
}
.son{
    
    width:200px;
    height:200px;
    background-color:blue;
}
</style>

4、grid布局

设置父元素为grid容器,然后设置单元格内容的水平垂直位置即可实现水平垂直居中(因为没有设置行和列所以整个wrap元素为一个单元格)
    .wrap{
    
        width: 200px;
        height: 200px;
        background: aqua;
        display: grid;  // 设置grid容器
        justify-items:center;
        align-items: center ;

    }
    .center{
    
        display: inline-block;
        width: 50px;
        height: 50px;
        background: red;

    }

    <div class="wrap">
        <div class="center">

        </div>
    </div>

5、table布局

display:table-cell属性的作用是让标签元素以表格单元格的形式呈现,类似于td标签,
vertical:middle设置元素垂直居中,
text-align:center设置水平居中
    .wrap{
    
        width: 200px;
        height: 200px;
        background: aqua;
        display: table-cell;
        vertical-align: middle;
        text-align: center;
    }
    .center{
    
        display: inline-block; // 如果是内联元素则不需要设置
        width: 50px;
        height: 50px;
        background: red;
    }
    
    <div class="wrap">
        <div class="center">

        </div>
    </div>

7、CSS的属性哪些可以继承?哪些不可以继承

CSS三大特性:继承、层叠、优先级
子元素可以继承父类元素的样式就叫继承
可以继承的:
1、字体的一些属性可以继承;font
2、文本的一些属性;line-height
3、元素的可见性;visibility:hidden
4、表格布局的属性;border-spacing
5、列表的属性;list-style
6、页面样式属性;page
7、声音的样式属性;
8、有没有用过预处理器
预处理器语言增加了变量、函数、混入等强大的功能
两种预处理器:SASS LESS

二、Javascript

1、JS有哪三部分组成

ECMAScript + 文档对象模型(DOM) + 浏览器对象模型(BOM)
ECMAScript:JS核心内容,描述了语言的基础语法,比如var,for循环,数据类型(字符串、数组、布尔值等等)
文档对象模型(DOM):DOM把整个HTML页面规划为元素构成的文档,
浏览器对象模型(BOM):对浏览器窗口进行访问和操作

2、JS有哪些内置对象

String、Boolean、Number、Array、Object、Function、Math、Date、RegExp、JSON…
常用的内置对象:Math : abs() sqrt() max() min()
var num = new Number(15);
Math.random()
生成一个0~1之间的随机小数
如果要生成0-54之间的随机整数:Math.floor(Math.random() * 54)
Math.floor(num)向上取整
Math.ceil(num)向下取整
Math.pow(x, y)求X的Y次方
Math.sqrt(x)求X的开平方
Math.trunc() - - 用于去除一个数的小数部分,返回整数部分。
Math.sign()方法判断一个数是正数、负数、零或者NaN。对于非数值,会将其转换 为数值。他会返回五种值:
参数为正数,返回+1;
参数为负数,返回-1;
参数为 0,返回0;
参数为-0,返回-0;
其他值,返回NaN。
Date: new Date()、 getYear()
let date = new Date(); //系统当前时间
let date = new Date(value); //value是距1970-1-1 0:0:0(UTC)依赖的毫秒值
let date = new Date(dateString); //dateString表示日期时间字符串“yyyy-MM-ddThh:mm:ss”
let date = new Date(year,month[, hour[, minutes[, seconds[, milliseconds]]]]);; //传递日期时间数字。month合理取值为0~11;
获取时间:
getFullYear() //获取四位年份
getMonth() //获取月份,返回值是0~11
getDate() //获取日期
getDay() //获取星期,返回值是0~6
getHours() //获取小时
getMinutes() //获取分钟
getSeconds() //获取秒
getMilliseconds() //获取毫秒
getTime() //获取距 1970-1-1 0:0:0 以来的毫秒值
设置时间:
setFullYear() //设置四位年份
setMonth() //设置月份,传值是0~11
setDate() //设置日期
setHours() //设置小时
setMinutes() //设置分钟
setSeconds() //设置秒
setMilliseconds() //设置毫秒
setTime() //设置距1970-1-1 0:0:0多少毫秒是什么时间(取负值的话就是1970年之前)
时间转换:
Date.parse() //解析,将日期时间字符串转换为表示时间的毫秒值
toString() //将日期时间字符串转换为字符串
toUTCString() //将日期时间转换为世界标准时间的字符串
valueOf() //返回Date对象的原始值。与getTime()一致。
tolSOString() //将日期时间转为格式为 YYYY-MM-DDTHH:mm:ss.sssZ 的字符串
toJSON() //返回 Date 对象的字符串形式。
获取日期时间毫秒值:
new Date.getTime()
Date.parse()
new Date().valueOf()
+new Date() //隐式类型转换的方法
Date.now() //ES5的方法
Array: 第三题有答案
String:
charAt(index) - - 获取index位置处的字符
charCodeAt(index) - - 获取index位置处字符的unicode编码
String.fromCharCode(code) - - 将unicode编码转换为对应的字符串
concat() - - 字符串连接
indexOf(sub) - - 查找符合条件的第一个字符串所在下标
lastIndexOf(sub) - - 查找符合条件的第一个字符串所在下标(从后往前查)
slice(start, end) - - 截取子字符串
subString(start, end) - - 截取子字符串
split() - - 切割字符串不传值的话就是直接把字符串用数组包起来,传值就是以值为分割
replace(oldString, newString) - - 替换
toUpperCase() - - 转换为大写
toLowerCase() - - 转换为小写
trim() - - 去掉前后空白
trimStart() - - 去除头部空白
trimLeft() - - 去除头部空白【trimStart的别名】
trimEnd() - - 去除尾部空白
trimRight() - - 去除尾部空白【trimEnd的别名】
replace(/^\s+|\s+$/g, ‘’) - - 去掉前后空白的兼容写法
includes(sub) - - 返回布尔值,表示是否找到了参数字符串。
startsWith(sub) - - 返回布尔值,表示参数字符串是否在原字符串的头部。
endsWith(sub) - - 返回布尔值,表示参数字符串是否在原字符串的尾部

3、操作数组的方法有哪些

push()
pop()
sort()
splice()
unshift()
shift()
reverse()
concat()
join()
map()
filter()
every()
some()
reduce()
isArray()
findIndex()

哪些方法会改变原数组:
push() pop() unshift() shift() sort() reverse() splice()

4、JS对数据类的检测方法有哪些

typeof()
对于基本数据类型没问题,遇到引用数据类型就不管用

console.log(typeof 666)//number
console.log(typeof [1,2,3])//object

instanceof()
只能判断引用数据类型,不能判断基本类型

console.log([] instanceof Array)//true
console.log('abc' instanceof String)//false

constructor()
几乎可以判断基本数据类型和引用数据类型;

console.log(('abc').constructor === String)//true
如果声明了一个构造函数并把他的原型指向了Array的时候,这时候就判断不出来了
let arr = []
Array.prototype.constructor = 'a'  //更改constructor
console.log(arr.constructor === Array)//false

Object.prototype.toString.call()最完美的解决方案

var opt = Object.prototype.toString
console.log(opt.call(2))//[object Number]
console.log(opt.call(true))[object Boolean]
console.log(opt.call('aaa'))[object String]
console.log(opt.call([]))[object Array]
console.log(opt.call({
    }))[object Object]

5、说一下闭包,闭包有什么特点

什么是闭包:函数嵌套函数,内部函数被外部函数返回并保存下来时,就会产生闭包
特点:可以重复利用变量,并且这个变量不会污染全局的一种机制;这个变量一直保存在内存中,不会被垃圾回收机制回收
缺点:闭包较多的时候会消耗内存,导致页面的性能下降,在IE浏览器中才会导致内存泄漏
使用场景:防抖、节流、函数嵌套函数避免全局污染的时候

function fn(a){
    
    return function(){
    
        console.log(a)    
    }
}
var fo = fn('abcd')
fo()

6、前端的内存泄漏怎么理解

JS里已经分配内存地址的对象,但是由于长时间没有释放或者没办法清除,造成长期占用内存的现象,会让内存资源大幅防雷,最终导致运行速度慢,甚至崩溃的情况。(内存泄漏是指在程序运行时,分配的内存没有被正确释放,导致内存空间的浪费,最终可能会导致程序崩溃或运行缓慢。)
垃圾回收机制
会导致内存泄漏的因素:一些为声明直接赋值的变量;一些未清空的定时器;过度的闭包;一些引用元素没有被清除

7、事件委托是什么

又叫事件代理。原理:利用事件冒泡的机制来实现,也就是说把子元素的事件绑定到了父元素的身上。如果子元素阻止了事件冒泡,那么委托也就不成立。
阻止事件冒泡:event.stoPropagation()
addEventLisenter(‘click’,函数名,true/false) 默认是false(事件冒泡),true(事件捕获)
好处:提高性能,减少事件的绑定;减少内存的占用

8、基本数据类型和引用数据类型的区别

基本数据类型:String Numebr Boolean undefined null
引用数据类型(复杂数据类型):Object Array function 、正则、日期对象
区别:
基本数据类型保存在栈内存中,保存的是一个具体的值;
引用数据类型保存在堆内存中,保存的是一个地址,(声明一个引用类型的变量的时候保存的是引用类型数据的地址。)eg:假如声明两个引用类型同时指向一个地址的时候,修改其中一个那么另外一个也会改变

9、说一下原型链

原型:一个普通对象,它是为构造函数的实例共享属性和方法,所有实例中引用的原型都是同一个对象
使用prototype可以把方法挂在原型上,内存只保存一份
__proto__可以理解为指针,实例对象()p1,p2)中的属性,指向了构造函数(Person)的原型(prototype)
原型链:一个实例对象在调用属性和方法的时候依次从实例本身到构造函数原型再到原型的原型上去查找的过程称为原型链

<script>
function Person(){
    
    this.say = function(){
    
        console.log('sing')    
    }
}
Person.prototype.look = function(){
    
    conole.log('look')
}
// 两个实例对象
var p1 = new Person()
var p2 = new Person()
p1.say()//sing
p2.say()//sing
p1.look()//look
p2.look()//look
console.log(p1.__proto__ === Person.prototype)//true
</script>

10、new操作符具体做了什么

<script>
function newFun(Fun,...args){
    
1、先创建空对象
    let newObj = {
    }
2、把空对象和构造函数通过原型链进行链接
    newObj.__proto__ = Fun.prototype
3、把构造函数的this指针绑定到新的空对象身上
    const result = Fun.apply(newObj,args)
4、根据构建的函数返回的类型判断,如果是值类型则返回对象,如果是引用类型,就要返回引用类型
    return result instanceof Object ? result : newObj
}
eg:
function Person(name){
    
    this.name = name
}
Person.prototype.say = function(){
    
    console.log('123456')
}
const p1 = newFun(Person,'zhangsan')
p1.say()//123456
console.log(p1)//Person{name:'zhangsan'}
</script>

11、JS是如何实现继承的

1、通过原型链
特点:继承父类原型上的属性和方法。
缺点:创建子类实例时,不能向父类构造函数中传参数,无法实现多继承

//父类
function Person(name) {
    
     this.name = name;
      this.sleep = function(){
    
        console.log(this.name + '正在睡觉')
   }
}
Person.prototype.change = "123木头人"
Person.prototype.sayHi = function () {
    
     console.log("您好啊!");
};
//子类
function Child(age) {
    
     this.age = age
}
Child.prototype = new Person()
Child.prototype.constructor = Child
let child = new Child(10)
console.dir(child)

2、通过借用构造函数继承
特点:解决了子类构造函数向父类构造函数中传递参数,可以实现多继承(call或者apply多个父类)
缺点:方法都在构造函数中定义,无法复用,不能继承原型上的属性和方法

//父类
function Person(name) {
    
     this.name = name;
      this.sleep = function(){
    
        console.log(this.name + '正在睡觉')
   }
}
Person.prototype.change = "123木头人"
Person.prototype.sayHi = function () {
    
     console.log("您好啊!");
};
//子类
function Child(name,age) {
    
    Person.call(this, name) 
 // Person.apply(this, [name]) //=> apply后面的参数是个数组.
    this.age = age;
}
let child = new Child("校长",10)
console.dir(child)

3、组合式继承
特点:把1和2的方法相结合,函数可以复用,可以继承属性和方法,并且可以继承原型的属性和方法
缺点:会挂载两次父类的属性和方法(有两个name和sleep),产生小bug,

//父类
function Person(name) {
    
     this.name = name;
      this.sleep = function(){
    
        console.log(this.name + '正在睡觉')
   }
}
Person.prototype.change = "123木头人"
Person.prototype.sayHi = function () {
    
     console.log("您好啊!");
};
//子类
function Child(name,age) {
    
    Person.call(this, name) 
 // Person.apply(this, [name]) //=> apply后面的参数是个数组.
    this.age = age;
}
Child.prototype = new Person()
Child.prototype.constructor = Child
let child = new Child("校长",10)
console.dir(child)

4、ES6的class类继承

//class 相当于es5中构造函数
//class中定义方法时,前后不能加function,全部定义在class的protopyte属性中
//class中定义的所有方法是不可枚举的
//class中只能定义方法,不能定义对象,变量等
//class和方法内默认都是严格模式
//es5中constructor为隐式属性
class People {
    
    constructor(name, age) {
    
        this.name = name;
        this.age = age;
    }
    sleep() {
    
        console.log(`${
      this.name} ${
      this.age} 正在睡觉`)
    }
}
//继承父类
class Child extends People {
    
    constructor(name, age) {
    
        //继承父类属性
        super(name, age);
    }
    sleep() {
    
        console.log(this);
        //继承父类方法
        super.sleep()
    }
} 
let child = new Child('小红',18); 
console.log(child);
child.sleep();    //小红 18 正在睡觉
总结:ES5继承和ES6继承的区别
ES5的继承实质上是先创建子类的实例对象,然后再将父类的方法添加到this上(Parent.call(this).
ES6的继承有所不同,实质上是先创建父类的实例对象this,然后再用子类的构造函数修改this。因为子类没有自己的this对象,所以必须先调用父类的super()方法,否则新建实例报错。

12、JS的设计原理是什么?

JS引擎、运行上下文、调用栈、事件循环、回调

13、JS中关于this指向的问题

1、全局对象中的this指向:指向的是window
2、全局作用域或者普通函数中的this:指向的是全局window
3、this永远指向最后调用他的那个对象(在不是箭头函数的情况下)
4、new关键词改变了this的指向
5、apply、call、bind可以改变this指向,不是箭头函数
6、箭头函数中的this:他的指向在定义的时候就已经确定了,箭头函数它没有this,看外层是否有函数,有就是外层函数的this,没有就是window
7、匿名函数中的this:永远指向了window,匿名函数的执行环境具有全局性,因此this指向window

14、script标签里的async和defer有什么区别?

当没有async和defer时候:浏览器会立刻加载并执行指定的脚本
有async:加载和渲染后面元素的过程将和script的加载和执行并行进行(异步)
有defer:加载和渲染后面元素的过程将和script的加载并行进行,但是他的执行事件要等所有元素解析完成之后才会执行

15、setTimeout最小执行时间是多少?

HTML5规定的内容:
setTimeout最小执行时间是4ms
setInterval最小执行时间是10ms

16、ES6和ES5有什么区别

JS的组成:ECMAScript BOM DOM
ES5: 全称ECMAScript5,2009年ECMAScript第五次修订,ECMSScript2009
ES6:全程ECMAScript6,2015年ECMAScript第六次修订,也成为ECMAScript2015,JS的下一个版本标准,解决ES5的不足

17、ES6的新特性有哪些

1、新增块级作用域:(let const)
let const :
不存在变量提升
存在暂时性死区的问题
多了块级作用域的内容
不能在同一个作用域内重复声明
2、新增定义类的语法糖(class)
3、新增了一种基本数据类型(symbol:独一无二的值)
4、新增解构赋值
从数组或者对象中取值,然后给变量赋值的过程叫解构赋值。
5、新增了函数参数的默认值
6、给数组新增了API
7、对象和数组新增了扩展运算符
8、promise(异步编程的一种方案,主要解决异步的计算)

1、解决回调地狱的问题
	2、自身有all ,reject,resolved,race方法
	3、原型上才有then或者catch
	4、把异步操作队列化
	5、三种状态:pending(初始状态)、fulfilled(操作成功)、rejected(操作失败)
	6、状态是pending --> fulfilled(pending) --> rejected;一旦发生,状态就会凝固,不会再变
	asyncawait:同步代码做异步的操作,两者必须搭配使用
	async表明函数内有异步操作,调用函数会返回promise
	await是组成async的表达式,结果是取决于它等待的内容,如果是promise那就是	promise的结果,如果是普通函数就进行链式调用
	await后的promise如果是reject状态,那么整个async函数都会中断,后面代码不执行

9、新增了模块化(import,export)
10、新增了set和map数据结构
set就是不重复
map的key的类型不受限制
11、新增了generator
12、新增了箭头函数

箭头函数与普通函数有什么区别:
1、不能作为构造函数使用,不能用new关键字,箭头函数没有原型
2、箭头函数没有arguments
3、箭头函数不能用call,apply,bind去改变this指向
4this指向外层第一个函数的this

18、call,apply,bind三者有什么区别

都是改变this指向和函数的调用,call和apply的功能类似,只是传参的方法不同而已
call方法:传的是一个参数列表
apply:传递的是一个数组
bind:传参后不会立刻执行,会返回一个改变了this指向的函数,这个函数还是可以传参的,bind()()
call方法的性能要比apply好一些,所以call用更多一点

19、用递归的时候有没有遇到什么问题

如果一个函数内可以调用函数本身,这个就是递归函数。(函数内部调用自己)
特别注意:写递归必须要有退出条件return

20、如何实现一个深拷贝?

深拷贝就是完全拷贝一份新的对象,会在堆内存中开辟新的空间,拷贝的对象被修改后,原对象不受影响。
主要针对的是引用数据类型
方法:
1、扩展运算符
2、JSON.parse(JSON.stringify())
3、利用递归函数实现
1、扩展运算符

<script>
        let obj = {
    
            name: '张三',
            age: 18        
        }
        let obj1 = {
    ...obj}
        obj1.name = '王五'
        console.log(obj)//{name:'张三',age:18}
        console.log(obj1)//{name:'王五',age:18}
        缺点:这个方法只能实现第一层,当有多层的时候还是浅拷贝

2、JSON.parse(JSON.stringify())

let obj = {
    
            name: '张三',
            age: 18,
            say(){
    
                console.log('say hello')            
            }      
        }
        let obj1 = JSON.parse(JSON.stringify(obj))
        obj1.name = '王五'
        console.log(obj)//{name:'张三',age:18,say:f}
        console.log(obj1)//{name:'王五',age:18}
        缺点:该方法并不会拷贝内部函数

3、利用递归函数实现

 let origin = {
    
            name: '张三',
            age: 18,
            say(){
    
                console.log('say hello')            
            },
            arr:[[1,2],3,4,5]  
        }
        function exten(origin,deep){
    
            let obj = {
    }
            if(origin instanceof Array){
    
                obj = []            
            }        
            for(let key in origin){
    
                let value = origin[key]
                obj[key] = (!!deep && typeof value === 'object' && value !== null) ? exten(value,deep) : value     
            }
            return obj
        }
        const oo = exten(origin,true)
        oo.arr[0].push(888)
        console.log(origin)//{age:18,arr:[[1,2],3,4],name:'张三',say:f}
        console.log(oo)//{age:18,arr:[[1,2,888],3,4],name:'张三',say:f}
    <script>

21、说一下事件循环?

JS是一个单线程的脚本语言
主线程、执行栈、任务队列、宏任务、微任务
主线程先执行同步任务,然后才去执行任务队列里的任务,如果在执行宏任务之前有微任务,那么要先执行微任务。全部执行完之后等待主线程的调用,调用完之后再去任务队列中查看是否有异步任务,这样一个循环往复的过程就是事件循环。

22、ajax是什么?怎么实现的

ajax是创建交互式网页应用的网页开发技术
在不重新加载整个网页的前提下,与服务器交换数据并更新部分内容
原理:通过XmlHttpRequest对象向服务器发送异步请求,然后从服务器拿到数据,最后通过JS操作DOM的形式更新页面
1、创建XmlHttpRequest对象 简称为xmh
2、通过xmh对象里的open()方法和服务器建立链接
3、构建请求所需的数据,并通过xmh对象的send()方法发送给服务器
4、通过xmh对象的onreadystate 里的change事件来监听服务器和你的通信状态
5、接收并处理服务器响应的数据结果
6、把处理的数据更新到HTML页面上

23、get和post有什么区别?

1、get一般是获取数据,post一般是提交数据
2、get参数会放在url上,所以安全性比较差,post是放在body中
3、get请求刷新服务器或退回是没有影响的,post请求退回时会重新提交数据
4、get请求是会被缓存,post请求不会被缓存
5、get请求会被保存在浏览器历史记录中,post不会
6、get请求只能进行url编码,post请求支持很多种(文件,表单。。。)
7、底层原理(面试的时候不会就不用提,要不然就尴尬了)

24、promise的内部原理是什么?他的优缺点是什么?

Promise是一个对象,封装了一个异步操作并且还可以获取成功或者失败的结果
Promise主要是解决回调地狱的问题,之前如果异步任务比较多,同时他们之间有相互依赖的关系,就只能使用回调函数处理,这样就容易形成回调地狱,代码的可读性差,可维护性也很差。
Promise有三种状态:pending初始状态、 fulfilled成功状态、 rejected失败状态
状态改变只会有两种情况,1、penging–>fulfilled
2、pending–>rejected
缺点:1、我们无法取消promise,一旦创建会立即执行,不能中途取消
2、如果不设置回调,promise内部抛出的错误就无法反馈到外面
3、若当前处于pending状态时,无法得知目前在哪个阶段。
原理:
构造一个Promise实例,实例需要传递函数的参数,这个函数有两个形参,分别都是函数类型,一个是resolve一个是reject;
Promise身上还有then方法,这个方法就是来指定状态改变时的确定操作,resolve是执行第一个函数,reject是执行第二个函数

25、promise和async await的区别是什么?

1、两个都是处理异步请求的方式
2、Promise是ES6的语法,async是ES7的语法
3、async await是基于Promise实现的,他和Promise都是非阻塞性的
优缺点:
1、Promise是返回对象我们要用then 和 catch方法去处理和捕获异常,并且书写方式是链式,容易造成代码重叠,不好维护,async await是通过try catch进行捕获异常
2、async await最大的优点就是能让代码看起来同步一样,只要遇到await就会立刻返回结果,然后在执行后面的操作,Promise是通过.then()的方式返回,会出现请求还没返回,就执行了后面的操作。

26、浏览器的存储方式有哪些?

1、cookies
H5标准前的本地存储方式
优点:兼容性好,请求头自带cookie
缺点:存储量小,资源浪费,使用麻烦(需要进行封装)
2、localstorage
H5加入的以键值对为标准的方式
优点:操作方便,永久存储,兼容性较好
缺点:保存值的类型被限定,浏览器在隐私模式下不可读取,不能被爬虫
3、sessionstorage
当前页面关闭后就会立刻清理,会话级别的存储方式
4、indexedDB
H5标准的存储方式

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_44740072/article/details/131464545

智能推荐

JWT(Json Web Token)实现无状态登录_无状态token登录-程序员宅基地

文章浏览阅读685次。1.1.什么是有状态?有状态服务,即服务端需要记录每次会话的客户端信息,从而识别客户端身份,根据用户身份进行请求的处理,典型的设计如tomcat中的session。例如登录:用户登录后,我们把登录者的信息保存在服务端session中,并且给用户一个cookie值,记录对应的session。然后下次请求,用户携带cookie值来,我们就能识别到对应session,从而找到用户的信息。缺点是什么?服务端保存大量数据,增加服务端压力 服务端保存用户状态,无法进行水平扩展 客户端请求依赖服务.._无状态token登录

SDUT OJ逆置正整数-程序员宅基地

文章浏览阅读293次。SDUT OnlineJudge#include<iostream>using namespace std;int main(){int a,b,c,d;cin>>a;b=a%10;c=a/10%10;d=a/100%10;int key[3];key[0]=b;key[1]=c;key[2]=d;for(int i = 0;i<3;i++){ if(key[i]!=0) { cout<<key[i.

年终奖盲区_年终奖盲区表-程序员宅基地

文章浏览阅读2.2k次。年终奖采用的平均每月的收入来评定缴税级数的,速算扣除数也按照月份计算出来,但是最终减去的也是一个月的速算扣除数。为什么这么做呢,这样的收的税更多啊,年终也是一个月的收入,凭什么减去12*速算扣除数了?这个霸道(不要脸)的说法,我们只能合理避免的这些跨级的区域了,那具体是那些区域呢?可以参考下面的表格:年终奖一列标红的一对便是盲区的上下线,发放年终奖的数额一定一定要避免这个区域,不然公司多花了钱..._年终奖盲区表

matlab 提取struct结构体中某个字段所有变量的值_matlab读取struct类型数据中的值-程序员宅基地

文章浏览阅读7.5k次,点赞5次,收藏19次。matlab结构体struct字段变量值提取_matlab读取struct类型数据中的值

Android fragment的用法_android reader fragment-程序员宅基地

文章浏览阅读4.8k次。1,什么情况下使用fragment通常用来作为一个activity的用户界面的一部分例如, 一个新闻应用可以在屏幕左侧使用一个fragment来展示一个文章的列表,然后在屏幕右侧使用另一个fragment来展示一篇文章 – 2个fragment并排显示在相同的一个activity中,并且每一个fragment拥有它自己的一套生命周期回调方法,并且处理它们自己的用户输_android reader fragment

FFT of waveIn audio signals-程序员宅基地

文章浏览阅读2.8k次。FFT of waveIn audio signalsBy Aqiruse An article on using the Fast Fourier Transform on audio signals. IntroductionThe Fast Fourier Transform (FFT) allows users to view the spectrum content of _fft of wavein audio signals

随便推点

Awesome Mac:收集的非常全面好用的Mac应用程序、软件以及工具_awesomemac-程序员宅基地

文章浏览阅读5.9k次。https://jaywcjlove.github.io/awesome-mac/ 这个仓库主要是收集非常好用的Mac应用程序、软件以及工具,主要面向开发者和设计师。有这个想法是因为我最近发了一篇较为火爆的涨粉儿微信公众号文章《工具武装的前端开发工程师》,于是建了这么一个仓库,持续更新作为补充,搜集更多好用的软件工具。请Star、Pull Request或者使劲搓它 issu_awesomemac

java前端技术---jquery基础详解_简介java中jquery技术-程序员宅基地

文章浏览阅读616次。一.jquery简介 jQuery是一个快速的,简洁的javaScript库,使用户能更方便地处理HTML documents、events、实现动画效果,并且方便地为网站提供AJAX交互 jQuery 的功能概括1、html 的元素选取2、html的元素操作3、html dom遍历和修改4、js特效和动画效果5、css操作6、html事件操作7、ajax_简介java中jquery技术

Ant Design Table换滚动条的样式_ant design ::-webkit-scrollbar-corner-程序员宅基地

文章浏览阅读1.6w次,点赞5次,收藏19次。我修改的是表格的固定列滚动而产生的滚动条引用Table的组件的css文件中加入下面的样式:.ant-table-body{ &amp;amp;::-webkit-scrollbar { height: 5px; } &amp;amp;::-webkit-scrollbar-thumb { border-radius: 5px; -webkit-box..._ant design ::-webkit-scrollbar-corner

javaWeb毕设分享 健身俱乐部会员管理系统【源码+论文】-程序员宅基地

文章浏览阅读269次。基于JSP的健身俱乐部会员管理系统项目分享:见文末!

论文开题报告怎么写?_开题报告研究难点-程序员宅基地

文章浏览阅读1.8k次,点赞2次,收藏15次。同学们,是不是又到了一年一度写开题报告的时候呀?是不是还在为不知道论文的开题报告怎么写而苦恼?Take it easy!我带着倾尽我所有开题报告写作经验总结出来的最强保姆级开题报告解说来啦,一定让你脱胎换骨,顺利拿下开题报告这个高塔,你确定还不赶快点赞收藏学起来吗?_开题报告研究难点

原生JS 与 VUE获取父级、子级、兄弟节点的方法 及一些DOM对象的获取_获取子节点的路径 vue-程序员宅基地

文章浏览阅读6k次,点赞4次,收藏17次。原生先获取对象var a = document.getElementById("dom");vue先添加ref <div class="" ref="divBox">获取对象let a = this.$refs.divBox获取父、子、兄弟节点方法var b = a.childNodes; 获取a的全部子节点 var c = a.parentNode; 获取a的父节点var d = a.nextSbiling; 获取a的下一个兄弟节点 var e = a.previ_获取子节点的路径 vue