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

技术标签: 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

智能推荐

2020最新Java面试题-程序员宅基地

文章浏览阅读2.7k次,点赞3次,收藏14次。@TOC1、面试题模块汇总面试题包括以下十九个模块:Java 基础、容器、多线程、反射、对象拷贝、Java Web 模块、异常、网络、设计模式、Spring/Spring MVC、Spring Boot/Spring Cloud、Hibernate、Mybatis、RabbitMQ、Kafka、Zookeeper、MySql、Redis、JVM 。如下图所示:可能对于初学者不需要后面的框架和 ...

Apache Dubbo讲义_apach dubbo讲义-程序员宅基地

文章浏览阅读90次。分布式RPC框架Apache Dubbo1. 软件架构的演进过程软件架构的发展经历了由单体架构、垂直架构、SOA架构到微服务架构的演进过程,下面我们分别了解一下这几个架构。1.1 单体架构架构说明:​ 全部功能集中在一个项目内(All in one)。架构优点:​ 架构简单,前期开发成本低、开发周期短,适合小型项目。架构缺点:​ 全部功能集成在一个工程中,对于大型项目不易开发、扩展和维护。​ 技术栈受限,只能使用一种语言开发。​ _apach dubbo讲义

聊聊zero-shot learning 和 one-shot learning-程序员宅基地

文章浏览阅读778次。Palatucci, Mark, et al. "Zero-shot learning with semantic output codes."Advances in ..._one-shot/zero-shot learning:

webSocket入门小案例(搭建实时交互的群聊+点对点的交流)_websocket入门案例-程序员宅基地

文章浏览阅读2.9k次。​WebSocket是一种在单个TCP连接上进行全双工通信的协议。WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。​_websocket入门案例

【HDU - 3308】 LCIS 【线段树+单点更新+区间合并】_given n integers. you have two operations: u a b: -程序员宅基地

文章浏览阅读304次。Given n integers. You have two operations: U A B: replace the Ath number by B. (index counting from 0) Q A B: output the length of the longest consecutive increasing subsequence (LCIS) in [a, b]._given n integers. you have two operations: u a b: replace the ath number by

WPF-设置窗体显示在右下角_wpf 窗口显示在右下角-程序员宅基地

文章浏览阅读2.8k次。 private void Button_Click(object sender, RoutedEventArgs e) { Win_Display_Position win = new Win_Display_Position(); //显示在右下角 double xpos = this.Left+this..._wpf 窗口显示在右下角

随便推点

NFT项目成功的底层逻辑是什么?非蓝筹NFT项目怎么破局?_nft底层逻辑是-程序员宅基地

文章浏览阅读650次。一.背景4月,随着moonbirds 短时间破纪录交易额引爆市场,bayc土地即将发行带领yuga club家族蓝筹猛涨,村上隆花和NBA在科学家们几百万份邮件和漏洞攻击中无法抵挡,pass通证类项目也在细分赛道中逐渐真香, NFT市场整体迎来了一波小行情。但蓝筹市场的火热,也加剧着NFT市场本就严重的马太效应,就如那句老话,金钱往往流向不缺钱的人,苦难往往流向能吃苦的人,对应到NFT市场中,优质项目的入场券流向了不缺钱的鲸鱼和顶尖科学家口袋,破发归零土狗项目流向了没钱希望暴富但被割的韭菜._nft底层逻辑是

认识MyBatis与Mybatis-plus及两者的区别_mybatis和mybatisplus的区别-程序员宅基地

文章浏览阅读2.3w次,点赞41次,收藏264次。一、认识Mybatis MyBatis 是持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Ordinary Java Object,普通的 Java对象)映射成数据库中的记录。1、功能架构Mybatis的功能架构分为三层_mybatis和mybatisplus的区别

50个最常用的UNIX / Linux命令(示例)_xp24g top-程序员宅基地

文章浏览阅读807次。This article provides practical examples for 50 most frequently used commands in Linux / UNIX.This is not a comprehensive list by any means, but this should give you a jumpstart on some of the com_xp24g top

hybrid app初体验,和react-native一起飞_hybrid能用react吗-程序员宅基地

文章浏览阅读1.7k次。第一次启动了react-native的示例,今天主要把其中遇到的坑与解决的办法分享给大家。如有疏漏、错误还望指正。首先还是要从hybrid app这个概念说起(如果对于这个过程不感兴趣的同学,可以直接往下翻,从开始配置react-native看起)。hybrid app就是混合应用。从我个人的理解,本以为就是在原生的app里面嵌入一些网页(webview),直到最近去体会了一把ionic,以及rea_hybrid能用react吗

1.物联网射频识别,RFID概念、组成、中间件、标准,全球物品编码——EPC码_epc 系统 rfid 实验d-think-程序员宅基地

文章浏览阅读1.7k次。可以配置和监视ISO/IEC 18000-6TypeC中防碰撞算法的时隙帧数、Q参数、发射功率、接收灵敏度、调制速率等,可以控制和监视选择命令、识读过程、会话过程等。读写器本质是射频无线数据采集设备。RFID标签靠近RFID读写器时,读写器会发送无线电波激活标签,标签接收到激活信号后会返回存储在标签内部的信息,读写器接收到信息后可以对其进行处理,如存储、传输或处理数据。但对于多数系统,需要有计算机系统组成的系统高层,对一个或多个读写器采集的标签数据进行整合,从而完成数据的查询、管理和数据交互等功能。_epc 系统 rfid 实验d-think

Import语句基础_import aie 语句-程序员宅基地

文章浏览阅读1.5k次,点赞4次,收藏7次。1 问题在 Java 中,如果给出一个完整的限定名,包括包名、类名,那么 Java 编译器就可以很容易地定位到源代码或者类。import 语句就是用来提供一个合理的路径,使得编译器可以找到某个类。2 方法1.import导入声明可分为两种:1) 单类型导入(single-type-import)例: 2) 按需类型导入(type-import-on-demand)例:2. 举例java.util..._import aie 语句

推荐文章

热门文章

相关标签