文末
逆水行舟不进则退,所以大家要有危机意识。
同样是干到35岁,普通人写业务代码划水,榜样们深度学习拓宽视野晋升管理。
这也是为什么大家都说35岁是程序员的门槛,很多人迈不过去,其实各行各业都是这样都会有个坎,公司永远都缺的高级人才,只用这样才能在大风大浪过后,依然闪耀不被公司淘汰不被社会淘汰。
为了帮助大家更好温习重点知识、更高效的准备面试,特别整理了《前端工程师核心知识笔记》电子稿文件。
内容包括html,css,JavaScript,ES6,计算机网络,浏览器,工程化,模块化,Node.js,框架,数据结构,性能优化,项目等等。
269页《前端大厂面试宝典》
包含了腾讯、字节跳动、小米、阿里、滴滴、美团、58、拼多多、360、新浪、搜狐等一线互联网公司面试被问到的题目,涵盖了初中级前端技术点。
开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】
前端面试题汇总
复制代码
相比于 getBoundingClientRect,它的优点是不会引起重绘回流。兼容性如下
图片懒加载
图片懒加载的原理主要是判断当前图片是否到了可视区域这一核心逻辑实现的。这样可以节省带宽,提高网页性能。传统的突破懒加载是通过监听 scroll 事件实现的,但是 scroll 事件会在很短的时间内触发很多次,严重影响页面性能。为提高页面性能,我们可以使用 IntersectionObserver 来实现图片懒加载。
const imgs = document.querySelectorAll(‘img[data-src]’)
const config = {
rootMargin: ‘0px’,
threshold: 0
}
let observer = new IntersectionObserver((entries, self) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
let img = entry.target
let src = img.dataset.src
if (src) {
img.src = src
img.removeAttribute(‘data-src’)
}
// 解除观察
self.unobserve(entry.target)
}
})
}, config)
imgs.forEach((image) => {
observer.observe(image)
})
复制代码
无限滚动
无限滚动(infinite scroll)的实现也很简单。
var intersectionObserver = new IntersectionObserver(function (entries) {
// 如果不可见,就返回
if (entries[0].intersectionRatio <= 0) return
loadItems(10)
console.log(‘Loaded new items’)
})
// 开始观察
intersectionObserver.observe(document.querySelector(‘.scrollerFooter’))
复制代码
getComputedStyle()
DOM2 Style 在 document.defaultView
上增加了 getComputedStyle()方法,该方法返回一个 CSSStyleDeclaration
对象(与 style 属性的类型一样),包含元素的计算样式。
API
document.defaultView.getComputedStyle(element[,pseudo-element])
// or
window.getComputedStyle(element[,pseudo-element])
复制代码
这个方法接收两个参数:要取得计算样式的元素和伪元素字符串(如":after")。如果不需要查询伪元素,则第二个参数可以传 null。
复制代码
和 style 的异同
getComputedStyle 和 element.style 的相同点就是二者返回的都是 CSSStyleDeclaration 对象。而不同点就是:
-
element.style 读取的只是元素的内联样式,即写在元素的 style 属性上的样式;而 getComputedStyle 读取的样式是最终样式,包括了内联样式、嵌入样式和外部样式。
-
element.style 既支持读也支持写,我们通过 element.style 即可改写元素的样式。而 getComputedStyle 仅支持读并不支持写入。我们可以通过使用 getComputedStyle 读取样式,通过 element.style 修改样式
getBoundingClientRect
getBoundingClientRect() 方法返回元素的大小及其相对于视口的位置。
API
let DOMRect = object.getBoundingClientRect()
复制代码
它的返回值是一个 DOMRect 对象,这个对象是由该元素的 getClientRects() 方法返回的一组矩形的集合,就是该元素的 CSS 边框大小。返回的结果是包含完整元素的最小矩形,并且拥有 left, top, right, bottom, x, y, width, 和 height 这几个以像素为单位的只读属性用于描述整个边框。除了 width 和 height 以外的属性是相对于视图窗口的左上角来计算的。
应用场景
1、获取 dom 元素相对于网页左上角定位的距离
以前的写法是通过 offsetParent 找到元素到定位父级元素,直至递归到顶级元素 body 或 html。
// 获取dom元素相对于网页左上角定位的距离
function offset(el) {
var top = 0
var left = 0
do {
top += el.offsetTop
left += el.offsetLeft
} while ((el = el.offsetParent)) // 存在兼容性问题,需要兼容
return {
top: top,
left: left
}
}
var odiv = document.getElementsByClassName(‘markdown-body’)
offset(a[0]) // {top: 271, left: 136}
复制代码
现在根据 getBoundingClientRect 这个 api,可以写成这样:
var positionX = this.getBoundingClientRect().left + document.documentElement.scrollLeft
var positionY = this.getBoundingClientRect().top + document.documentElement.scrollTop
复制代码
2、判断元素是否在可视区域内
function isElView(el) {
var top = el.getBoundingClientRect().top // 元素顶端到可见区域顶端的距离
var bottom = el.getBoundingClientRect().bottom // 元素底部端到可见区域顶端的距离
var se = document.documentElement.clientHeight // 浏览器可见区域高度。
if (top < se && bottom > 0) {
return true
} else if (top >= se || bottom <= 0) {
// 不可见
}
return false
}
复制代码
requestAnimationFrame
window.requestAnimationFrame() 告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。
API
该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行。
window.requestAnimationFrame(callback)
复制代码
兼容性处理
window._requestAnimationFrame = (function () {
return (
window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
function (callback) {
window.setTimeout(callback, 1000 / 60)
}
)
})()
复制代码
结束动画
var globalID
function animate() {
// done(); 一直运行
globalID = requestAnimationFrame(animate) // Do something animate
}
globalID = requestAnimationFrame(animate) //开始
cancelAnimationFrame(globalID) //结束
复制代码
与 setTimeout 相比,requestAnimationFrame 最大的优势是由系统来决定回调函数的执行时机。具体一点讲,如果屏幕刷新率是 60Hz,那么回调函数就每 16.7ms 被执行一次,如果刷新率是 75Hz,那么这个时间间隔就变成了 1000/75=13.3ms,换句话说就是,requestAnimationFrame 的步伐跟着系统的刷新步伐走。它能保证回调函数在屏幕每一次的刷新间隔中只被执行一次,这样就不会引起丢帧现象,也不会导致动画出现卡顿的问题。这个 API 的调用很简单,如下所示:
var progress = 0
//回调函数
function render() {
progress += 1 //修改图像的位置
if (progress < 100) {
//在动画没有结束前,递归渲染
window.requestAnimationFrame(render)
}
}
//第一帧渲染
window.requestAnimationFrame(render)
复制代码
优点:
-
CPU 节能:使用 setTimeout 实现的动画,当页面被隐藏或最小化时,setTimeout 仍然在后台执行动画任务,由于此时页面处于不可见或不可用状态,刷新动画是没有意义的,完全是浪费 CPU 资源。而 requestAnimationFrame 则完全不同,当页面处理未激活的状态下,该页面的屏幕刷新任务也会被系统暂停,因此跟着系统步伐走的 requestAnimationFrame 也会停止渲染,当页面被激活时,动画就从上次停留的地方继续执行,有效节省了 CPU 开销。
-
函数节流:在高频率事件(resize,scroll 等)中,为了防止在一个刷新间隔内发生多次函数执行,使用 requestAnimationFrame 可保证每个刷新间隔内,函数只被执行一次,这样既能保证流畅性,也能更好的节省函数执行的开销。一个刷新间隔内函数执行多次时没有意义的,因为显示器每 16.7ms 刷新一次,多次绘制并不会在屏幕上体现出来。
应用场景
1、监听 scroll 函数
页面滚动事件(scroll)的监听函数,就很适合用这个 api,推迟到下一次重新渲染。
$(window).on(‘scroll’, function () {
window.requestAnimationFrame(scrollHandler)
})
复制代码
平滑滚动到页面顶部
const scrollToTop = () => {
const c = document.documentElement.scrollTop || document.body.scrollTop
if (c > 0) {
window.requestAnimationFrame(scrollToTop)
window.scrollTo(0, c - c / 8)
}
}
scrollToTop()
复制代码
2、大量数据渲染
比如对十万条数据进行渲染,主要由以下几种方法:
(1)使用定时器
//需要插入的容器
let ul = document.getElementById(‘container’)
// 插入十万条数据
let total = 100000
// 一次插入 20 条
let once = 20
//总页数
let page = total / once
//每条记录的索引
let index = 0
//循环加载数据
function loop(curTotal, curIndex) {
if (curTotal <= 0) {
return false
}
//每页多少条
let pageCount = Math.min(curTotal, once)
setTimeout(() => {
for (let i = 0; i < pageCount; i++) {
let li = document.createElement(‘li’)
li.innerText = curIndex + i + ’ : ’ + ~~(Math.random() * total)
ul.appendChild(li)
}
loop(curTotal - pageCount, curIndex + pageCount)
}, 0)
}
loop(total, index)
复制代码
(2)使用 requestAnimationFrame
//需要插入的容器
let ul = document.getElementById(‘container’)
// 插入十万条数据
let total = 100000
// 一次插入 20 条
let once = 20
//总页数
let page = total / once
//每条记录的索引
let index = 0
//循环加载数据
常用的JavaScript设计模式
-
单体模式
-
工厂模式
-
例模式
函数
-
函数的定义
-
局部变量和全局变量
-
返回值
-
匿名函数
-
自运行函数
-
闭包
开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】