// 传统方式
function query(name) {
const search = location.search.substr(1) // 类似 array.slice(1)除去第一个
// search: ‘a=10&b=20&c=30’
const reg = new RegExp((^|&)${name}=([^&]*)(&|$)
, ‘i’) // i表示大小写不区分
const res = search.match(reg)
if (res === null) {
return null
}
return res[2] // 固定写法 输出b对应的值20
}
query(‘b’)
// URLSearchParams
function query(name) {
const search = location.search
const p = new URLSearchParams(search)
return p.get(name)
}
console.log( query(‘b’) )
20. 介绍一下RAF requestAnimationFrame
在Web应用中,实现动画效果的方法比较多,Javascript 中可以通过定时器 setTimeout或者setInterval 来实现,css3 可以使用 transition 和 animation 来实现,html5 中的 canvas 也可以实现。除此之外,html5 还提供一个专门用于请求动画的API,那就是 requestAnimationFrame,顾名思义就是请求动画帧。
要想动画流畅,更新频率要60帧/秒,即16.67ms更新一次视图
setTimeout需要手动控制频率,而RAF浏览器会自动控制
后台标签或者隐藏iframe中(最小化),RAF会暂停,而setTimeout依然执行
// 3s 把宽度从 100px 变为 640px ,即增加 540px
// 60帧/s ,3s 180 帧 ,每次变化 3px
const $div1 = $(‘#div1’)
let curWidth = 100
const maxWidth = 640
// RAF
function animate() {
curWidth = curWidth + 3
$div1.css(‘width’, curWidth)
if (curWidth < maxWidth) {
window.requestAnimationFrame(animate) // 时间不用自己控制
}
}
animate()
手写代码题
=========
1. 手写深度比较,模拟lodash.isEqual
// 判断是否是对象或数组(不考虑函数)
function isObject(obj) {
return typeof obj === ‘object’ && obj !== null
}
// 全相等(深度)
function isEqual(obj1, obj2) {
// 首先判断是否是对象
if (!isObject(obj1) || !isObject(obj2)) {
// 值类型(注意,参与 equal 的一般不会是函数)
return obj1 === obj2
}
if (obj1 === obj2) {
return true
}
// 两个都是对象或数组,而且不相等
// 1. 先取出 obj1 和 obj2 的 keys ,比较个数
const obj1Keys = Object.keys(obj1)
const obj2Keys = Object.keys(obj2)
if (obj1Keys.length !== obj2Keys.length) {
return false
}
// 2. 以 obj1 为基准,和 obj2 依次递归比较
for (let key in obj1) {
// 比较当前 key 的 val —— 递归!!!
const res = isEqual(obj1[key], obj2[key])
if (!res) {
return false
}
}
// 3. 全相等
return true
}
// 测试
const obj1 = {
a: 100,
b: {
x: 100,
y: 200
}
}
const obj2 = {
a: 100,
b: {
x: 100,
y: 200
}
}
// console.log( obj1 === obj2 )
console.log( isEqual(obj1, obj2) )
const arr1 = [1, 2, 3]
const arr2 = [1, 2, 3, 4]
2. 手写字符串trim方法,保证兼容(正则表达式)
trim 掐头去尾去空格
String.prototype.trim = unction () {
return this.replace(/^\s+/,‘’).replace(/\s+$/,‘’) // \s字符
}
3.将url参数解析为JS对象
// 传统方法,分析search
function queryToObj() {
const res = {}
const search = location.search.substr(1) // 去掉?
search.split(‘&’).forEach(paramStr => {
const arr = paramStr.split(‘=’)
const key = arr[0]
const key = arr[1]
res[key] = val
})
return res
}
// 使用URLSearchParams
function queryToObj() {
const res = {}
const pList = new URLSearchParams(location.search)
pList.forEach((val, key) => {
res[key] = val
})
return res
}
4. 手写flatern考虑多层级
将[1, 2, [3, 4, [10, 20, [100, 200]]], 5]变为[1, 2, 3, 4, 10, 20, 100, 200, 5]
function flat(arr) {
// 验证 arr 中,还有没有深层数组 [1, 2, [3, 4]]
const isDeep = arr.some(item => item instanceof Array)
if (!isDeep) {
return arr // 已经是 flatern [1, 2, 3, 4]
}
// oncat只能解决单层[]
const res = Array.prototype.concat.apply([], arr)
return flat(res) // 递归
}
const res = flat( [1, 2, [3, 4, [10, 20, [100, 200]]], 5] )
console.log(res)
5. 数组去重
// 传统方式
function unique(arr) {
const res = []
arr.forEach(item => {
if (res.indexOf(item) < 0) { // 没有当前元素
res.push(item)
}
})
return res
}
// 使用 Set (无序,不能重复)
function unique(arr) {
const set = new Set(arr)
return […set] // 解构
}
const res = unique([30, 10, 20, 30, 40, 10])
console.log(res)
6. 手写深拷贝
function deepClone(obj = {}) {
if (typeof obj !== ‘object’ || obj == null) {
// obj 是 null ,或者不是对象和数组,直接返回
return obj
}
// 初始化返回结果
let result
if (obj instanceof Array) { // 判断是否为数组
result = []
} else {
result = {}
}
for (let key in obj) {
// 保证 key 不是原型的属性
if (obj.hasOwnProperty(key)) {
// 递归调用!!!
result[key] = deepClone(obj[key])
}
}
// 返回结果
return result
}
7. 手写一个简易的jQuery,考虑插件和扩展性
class jQuery {
constructor(selector) {
const result = document.querySelectorAll(selector)
const length = result.length
for (let i = 0; i < length; i++) {
this[i] = result[i]
}
this.length = length
this.selector = selector
}
get(index) {
return this[index]
}
each(fn) {
for (let i = 0; i < this.length; i++) {
const elem = this[i]
fn(elem)
}
}
on(type, fn) {
return this.each(elem => {
elem.addEventListener(type, fn, false)
})
}
// 扩展很多 DOM API
}
// 插件
jQuery.prototype.dialog = function (info) {
alert(info)
}
// 扩展 “造轮子”
class myJQuery extends jQuery {
constructor(selector) {
super(selector)
}
// 扩展自己的方法
addClass(className) {
}
style(data) {
}
}
8. 手写bind函数
// 模拟 bind
Function.prototype.bind1 = function () {
// 将参数拆解为数组
const args = Array.prototype.slice.call(arguments)
// 获取 this(数组第一项)
const t = args.shift() // 拿走数组第一项
// fn1.bind(…) 中的 fn1
const self = this
// bind返回一个函数
return function () {
return self.apply(t, args)
}
}
function fn1(a, b, c) {
console.log(‘this’, this)
console.log(a, b, c)
return ‘this is fn1’
}
const fn2 = fn1.bind1({x: 100}, 10, 20, 30)
const res = fn2()
console.log(res)
9. 通用的事件监听函数
function bindEvent(elem, type, selector, fn) { // selector是个css选择器
if (fn == null) { // 判断只传入三个参数
fn = selector
selector = null
}
elem.addEventListener(type, event => {
const target = event.target
if (selector) {
// 有selector时是代理绑定
if (target.matches(selector)) { // 判断DOM元素是否符合css选择器
fn.call(target, event)
}
} else {
// selector为空,只有三个参数,是普通绑定
fn.call(target, event)
}
})
}
// 普通绑定
const btn1 = document.getElementById(‘btn1’)
bindEvent(btn1, ‘click’, function (event) { // 注意不能使用箭头函数,否则获取的是上级window
// console.log(event.target) // 获取触发的元素
event.preventDefault()
alert(this.innerHTML) // this
})
// 代理绑定
const div3 = document.getElementById(‘div3’)
bindEvent(div3, ‘click’, ‘a’, function (event) {
event.preventDefault() // 阻止默认行为(页面页面调转)
alert(this.innerHTML) // 如果使用箭头函数的写法 event.target.innerHTML
})
10. 手写防抖和节流
// 防抖封装
function debounce(fn, delay = 500) {
// timer 是闭包中的
let timer = null
// 返回一个函数
return function () {
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(() => {
fn.apply(this, arguments)
timer = null
}, delay)
}
}
input1.addEventListener(‘keyup’, debounce(function (e) {
console.log(e.target)
console.log(input1.value)
}, 600))
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024c (备注前端)
常用的JavaScript设计模式
-
单体模式
-
工厂模式
-
例模式
函数
-
函数的定义
-
局部变量和全局变量
-
返回值
-
匿名函数
-
自运行函数
-
闭包
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024c (备注前端)**
[外链图片转存中…(img-mUZTrPcc-1712768839637)]
常用的JavaScript设计模式
-
单体模式
-
工厂模式
-
例模式
函数
-
函数的定义
-
局部变量和全局变量
-
返回值
-
匿名函数
-
自运行函数
-
闭包
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-wXrsAGen-1712768839637)]