常见面试题总结归纳(四)

4 篇文章 0 订阅

从输入url到渲染页面的整个过程

基础答案:
从三个方面来说:
1.加载资源的形式。
资源的一般形式有html,媒体文件(图片,视频),js,css等。
2.加载资源的过程。
DNS解析:域名 -> IP地址
浏览器根据IP地址想服务器发起Http请求
服务器处理http请求,并返回给浏览器
3.渲染页面的过程。
根据HTML代码生成DOM Tree
根据CSS代码生成CSSOM
将DOM Tree和CSSOM整合形成Rendeer Tree
根据RenderTree渲染页面
遇到

所以常见的优化中,css的引入放在head里面,这样可以避免dom结构先按默认值渲染,而后加载到css的时候,因cssom和dom tree整合而重复渲染。
将scripe标签放在body最后也是这个道理。以免渲染到一半,遇到js了,完了以后又重新渲染。
我们更期望先渲染完dom结构,再执行js,可以加快视觉上的页面渲染速度。

window.onload跟DOMContentLoaded的区别

window.addEventListener('load',function(){
//   页面的全部资源加载完成后才执行,包括图片,视频
})
document.addEventListener('DOMContentLoaded',function(){
//   DOM渲染完即可执行,此时图片视频可能还未加载完成
})

所以用onload来做实际上不是很好的选择。

前端性能优化

这是一个综合性问题,没有标准答案,但要尽量全面,并加入自己的思考。
其中某些问题可能会单独提问:比如手写房防抖和节流。

性能优化原则:
多使用内存、缓存或其他方法,减少cpu计算量,减少网络加载耗时,空间换时间。

从哪里入手解决:
1.让加载更快
减少资源体积:压缩代码。(webpack生产环境打包压缩)
减少访问次数:合并代码,SSR服务端渲染,缓存
使用更快的网络:CDN

2.让渲染更快
CSS放在head,JS放在body最下面
尽早开始执行JS,用DOMContentLoaded触发
懒加载(图片懒加载,上滑加载更多等等)
对DOM查询进行缓存
频繁的DOM操作,合并到一起插入DOM结构
throttle和debounce

比如webpack打包会将所有的js文件整合成一个js文件,js文件在output的时候设置filename,加入[contenthash],可以让缓存命中加快。

静态资源加hash后缀,根据内容计算hash,文件内容不变,则hash不变,url不变,url和文件不变,则会自动触发http缓存机制,返回304。

SSR服务端渲染:将网页和数据一起加载,一起渲染。
非SSR(前后端分离):先加载网页,在加载数据,再重新渲染数据。(比如早期的JSP,ASP,PHP,现在的vue/React SSR)

Object.create()和new的区别

首先,Object.create()有两个参数:
1.proto:必选,是新建对象的原型对象。
2.propertisObject:可选,是新创建的实例对象上的属性。

// 首先,Object.create()有两个参数:
// 1.proto:必选,是新建对象的原型对象。
// 2.propertisObject:可选,是新创建的实例对象上的属性。
var x = Object.create({
    a: 'A',
    b: 'B',
    c: 'C'
})

console.log(x) //{}
console.log(x.__proto__) //可以看到abc

var xx = Object.create({
    a: 'A',
    b: 'B',
    c: 'C'
}, { //第二个属性相当于Object.defineProperty()
    'a11': {
        value: 'A11'
    },
    'b11': {
        value: 'B11'
    }
})

console.log(xx)

var AObj = {
    a: 'A',
    b: 'B',
    c: function () {
        console.log('C')
    }
}

var _AObj = Object.create(AObj, {
    'text': {
        value: 'Object.create方法实现的继承'
    }
})
console.log(_AObj)
_AObj.c()
// 这里可以看到_AObj的__proto__指向的就是他的父类
// 而new操作符,它创建的实例的__proto__是自动指向构造函数的prototype的


再回顾一下new操作符到底做了什么
1.创建一个新对象。
2.将构造函数的作用域赋给新对象(因此this就指向了这个新对象)
3.执行构造函数中的代码(也就是为新对象添加属性)
4.返回新对象

// 用Object.create来模拟实现new关键字
let Parent = function (a) {
    this.a = a;
}

Parent.prototype.Im = function () {
    console.log(this.a)
}

let myNew = function (Parent, ...rest) {
    let child = Object.create(Parent.prototype)
    Parent.apply(child, rest)
    return child
}

let child1 = myNew(Parent, 'gary')

child1.Im()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值