面试题汇总©
# 1.从输入一个URL地址到浏览器完成渲染的整个过程
- 浏览器地址栏输入URL并回车
- 浏览器查找当前URL是否存在缓存,并比较缓存是否过期
- DNS解析URL对应的IP
- 根据IP建立TCP连接(三次握手)
- 发送http请求
- 服务器处理请求,浏览器接受HTTP响应
- 浏览器解析并渲染页面
- 关闭TCP连接(四次握手)
详解:从输入一个URL地址到浏览器完成渲染的整个过程 (opens new window)
# 2.css优先级怎么计算的
- 第一优先级:!important会覆盖页面内任何位置的元素样式
- 1.内联样式,如style="color:green",权值为1000
- 2.ID选择器,如#app,权值为0100
- 3.类,伪类,属性选择器,如.foo,:first-child,div[class="foo"],权值为0010
- 4.标签,伪元素选择器,如div::frist-line,权值为0001
- 5.通配符,子类选择器,兄弟选择器,如*,>,+,权值为0000
- 6.继承的样式没有权值
# 3.HTTP状态码
- 200:请求被正常处理
- 204:请求被受理但没有资源可以返回
- 206:客户端只是请求资源中的一部分,服务器只对请求的部分资源执行GET方法,相应报文中通过Content-Range指定范围的资源。
- 301:永久性重定向
- 302:临时重定向
- 303:与302状态码有相似功能,只是它希望客户端在请求一个URI的时候,能通过GET方法重定向到另一个URI上
- 304:(未修改) 自从上次请求后,请求的网页未修改过。 服务器返回此响应时,不会返回网页内容。
- 307:临时重定向,与302类似,只是强制要求使用POST方法
- 400:(错误请求) 服务器不理解请求的语法(一般为参数错误)。
- 401:(未授权) 请求要求身份验证。 对于需要登录的网页,服务器可能返回此响应。
- 403:(禁止) 服务器拒绝请求。(一般为客户端的用户权限不够)
- 404:(未找到) 服务器找不到请求的网页。
- 500:服务器内部错误
- 503:服务器正忙
# 4.HTTP2.0 做了哪些改进,3.0呢?
HTTP2.0 特性如下
- 二进制分帧传输
- 多路复用
- 头部压缩
- 服务器推送
Http3.0 相对于 Http2.0 是一种脱胎换骨的改变!
http 协议是应用层协议,都是建立在传输层之上的。我们也都知道传输层上面不只有 TCP 协议,
还有另外一个强大的协议 UDP 协议,2.0 和 1.0 都是基于 TCP 的,因此都会有 TCP 带来的硬伤以及局限性。
而 Http3.0 则是建立在 UDP 的基础上。所以其与 Http2.0 之间有质的不同。
http3.0 特性如下
- 连接迁移
- 无队头阻塞
- 自定义的拥塞控制
- 前向安全和前向纠错
# 5.position有哪些值,作用分别是什么
- static
static(没有定位)是position的默认值,元素处于正常的文档流中,会忽略left,top,right,bottom 和 z-index 属性。
- relative
relative(相对定位)是指给元素设置相对于原本位置的定位,元素并不脱离文档流,因此元素原本的位置会被保留,其他的元素位置不会受到影响
一般用在子元素相对于父元素进行定位
- absolute(绝对定位)是指给元素设置绝对的定位,相对定位的对象可以分为两种情况:
- 设置了absolute的元素如果存在有祖先元素设置了position为relative或者absolute,则这时元素的定位对象为此已设置position的祖先元素
- 如果并没有设置了position属性的祖先元素,则此时相对于body进行定位。
使用场景:跟随图标 图标使用不依赖定位父级的 absolute 和 margin 属性进行定位,这样,当文本的字符个数改变时,图标的位置可以自适应
- fixed 可以简单的说说特殊版的 absolute,fixed元素总是相对于body定位。
使用场景:侧边栏或者广告图
inherit 继承父元素的position属性,但需要注意的是 IE8 以及以往的版本都不支持 inherit 属性。
设置了 sticky 的元素,在屏幕范围(viewport)时该元素的位置并不受到定位影响(设置是 top、left 等属性无效),当该元素的位置将要移出偏移范围时,定位又会变成 fixed,根据设置的 left、top 等属性成固定位置的效果。
当元素在容器中被滚动超过指定的偏移值时,元素在容器内固定在指定位置。亦即如果你设置了 top: 50px,那么在 sticky 元素到达距离相对定位的元素顶部 50px 的位置时固定,不再向上移动(相当于此时 fixed 定位)。
# 6.new一个对象的过程中经历了什么「红宝书」
- 在内存中创建一个新对象。
- 这个新对象内部的[[Prototype]]特性被赋值为构造函数的prototype属性。
- 构造函数内部的this被赋值为这个新对象(即this指向新对象)。
- 执行构造函数内部的代码(给新对象添加属性)。
- 如果构造函数返回非空对象,则返回该对象;否则,返回刚创建的新对象。
ar a = new Foo("zhang","jake");
new Foo{
// 在内存中创造一个新对象
var obj = {};
// 给这个新对象内部的Prototype赋值为构造函数的prototype
obj.__proto__ = Foo.prototype;
// 构造函数内部的代码这样执行
var result = Foo.call(obj,"zhang","jake");
// 如果构造函数返回非空对象,则返回该对象;否则,返回刚刚创建的对象。
return typeof result === 'obj'? result : obj;
}
谁被new了,this就指向谁。
# 7.输出了啥
function test(person) {
person.age = 26
person = {
name: 'yyy',
age: 30
}
return person
}
const p1 = {
name: 'yck',
age: 25
}
const p2 = test(p1)
console.log(p1) // -> {name:'yck',age:26};默认的,被person.age更改了
console.log(p2) // -> {name:'yyy',age:30};挂载到原型上了
# 8.typeof 是否能正确判断类型?instanceof能正确判断对象的原理是什么?
typeof
对于原始类型来说,除了null
都可以显示正确的类型typeof
对于对象来说,除了函数都会显示object
,所以说typeof
并不能准确判断变量到底是什么类型
instanceof的内部机制是通过原型链来实现的
- 可以用来判断对象的正确类型
- 对于原始类型来说,你想直接通过 instanceof 来判断类型是不行的,当然我们还是有办法让 instanceof 判断原始类型的
class PrimitiveString {
static [Symbol.hasInstance](x){
return typeof x === 'String'
}
}
console.log('hello world' instanceof PrimitiveString) // true
- 其实自己写一个typeOf做更加准确的判断也未尝不可
function typeOf(obj){
return Object.prototype.toString.call(obj).slice(8,-1);
}
# 9.类型转化
在JS中类型转换只有三种情况:
- 转换为布尔值
- 转换为数字
- 转换为字符串
- 转Boolean
在条件判断的时候,除了
undefined
、null
、false
、NaN
、''、0、-0,其他所有值都转为true
,包括所有对象。
- 对象转原始类型
对象在转换类型的时候,会调用内置的 [[ToPrimitive]] 函数,对于该函数来说,算法逻辑一般来说如下:
- 如果已经是原始类型了,那就不需要转换了
- 如果需要转字符串类型就调用
x.toString()
,转换为基础类型的话就返回转换的值。不是字符串类型的话就先调用valueOf
,结果不是基础类型的话再调用toString
.
valueOf解释
valueOf方法由Object后面的每个对象继承。 每个内置的核心对象都会覆盖此方法以返回适当的值。如果对象没有原始值,则valueOf将返回对象本身。
- 调用
x.valueOf()
,如果转换为基础类型,就返回转换的值。 - 如果都没有返回原始类型,就会报错。
当然你也可以重写Symbol.toPrimitive
,该方法在转原始类型时调用优先级最高。
let a = {
valueOf(){
return 0
},
toString(){
return '1'
},
[Symbol.toPrimitive](){
return 2
}
}
1 + a // => 3
四则运算符
加法运算符不同于其他几个运算符,它有以下几个特点:
- 运算中其中一方为字符串,那么就会把另一方也转化为字符串
- 如果一方不是字符串或者数字,那么会将它转化为数字或者字符串
1 + '1' // '2'
true + true // 2
4 + [1,2,3] // "41,2,3"
另外对于加法还要注意这个表达式 'a' + + 'b'
'a' + + 'b' // -> "aNaN"
那么对于除了加法的运算符来说,只要其中一方是数字,那么另一方就会被转化为数字
4 * '3' // 12
4 * [] // 0
4 * [1,2] // NaN
比较运算符
- 如果是对象,就通过
toPrimitive
转换对象 - 如果是字符串,就通
unicode
字符串索引来比较
let a = {
valueOf() {
return 0
},
toString() {
return '1'
}
}
a > -1 // true
// a是对象,会通过valueOf转化为原始类型再比较值
# 10.keep-alive组件有什么用
如果你需要在组件切换的时候,保存一些组件的状态防止多次渲染,则可以使用
keep-alive
组件包裹需要保存的组件。
对于
keep-alive
组件来说,它拥有两个独有的生命周期钩子函数,分别为activated
和deactivated
。用keep-alive
包裹的组件在切换时不会进行销毁,而是缓存到内存中并执行deactivated
勾子函数,命中缓存渲染后会执行actived
勾子函数。
# 11.v-show 与 v-if 区别
v-show
只是在display: none
和display: block
之间切换。无论初始条件是什么都会被渲染出来,后面只需要切换 CSS,DOM 还是一直保留着的。所以总的来说v-show
在初始渲染时有更高的开销,但是切换开销很小,更适合于频繁切换的场景。
v-if
的话就得说到 Vue 底层的编译了。当属性初始为false
时,组件就不会被渲染,直到条件为true
,并且切换条件时会触发销毁/挂载组件,所以总的来说在切换时开销更高,更适合不经常切换的场景。
# 12.组件中 data 什么时候可以使用对象
组件复用时所有组件实例都会共享
data
,如果data
是对象的话,就会造成一个组件修改data
以后会影响到其他所有组件,所以需要将data
写成函数,每次用到就调用一次函数获得新的数据。
当我们使用
new Vue()
的方式的时候,无论我们将data
设置为对象还是函数都是可以的,因为new Vue()
的方式是生成一个根组件,该组件不会复用,也就不存在共享data
的情况了。
# 13.闭包,这个函数有哪几种操作方法。
定义:函数A里面有函数B,函数B可以访问到函数A里面的变量,那么函数B就是闭包。
for (var i = 1; i <= 5; i++) {
setTimeout(function timer() {
console.log(i)
}, i * 1000)
}
// 输出5个6
way1:划分作用域「let」
for(let i = 1;i <= 5; i++){
setTimeout(function timer() {
console.log(i)
},i * 1000)
}
way2:使用闭包方式
for(var i=1;i<=5;i++){
(function (j) {
setTimeout(function timer() {
console.log(j)
}, j*1000)
})(i)
}
way3:使用setTimeout
的第三个参数
for(var i=1;i<=5;i++){
setTimeout(function timer(j) {
console.log(j)
}, i*1000,i)
}
# 14.['1','2','3'].map(parseInt)
- 能够得到什么?
Ans :
[1,NaN,NaN]
map
函数的callback:
var new_array = arr.map(function callback(currentValue[,index[,array]])){
// Return element for new_array
}[,thisArg]
这个callback一共可以接收三个参数,其中第一个参数代表当前被处理的元素,而第二个参数代表该元素的索引。
而parseInt则是用来解析字符串的,使字符串成为指定基数的整数。
parseInt(string, radix)
接收两个参数,第一个表示被处理的值(字符串),第二个表示为解析时的基数。也就是说:“我们接受的处理的值是填入的字符串的,然后radix是索引”模拟
parseInt('1',0)
//radix
为0时,且string
参数不以0x
和0
开头时,按照10为基数处理。这个时候返回1.parseInt('2',1)
//基数为1(1进制)表示的数中,最大值小于2,所以无法解析,返回NaNparseInt('3',2)
//基数为2(2进制)表示的数中,最大值小于3,所以无法解析,返回NaN