- 👋 你好,我是陈大鱼头
- 👀 我是一枚前端工程师
- 💌 我的微信公众号是:鱼头的Web海洋(好久没更新了)
- 🏡 我的技术博客:https://blog.krissarea.com/
- 💬 微信号:krisChans95
- 📧 邮箱:[email protected]
krisachan / ying-study Goto Github PK
View Code? Open in Web Editor NEWsomething knowledge about web
something knowledge about web
给定一个 “扁平化” 字典对象,其键以点分隔。
例如:
{
'A': 1,
'B.B': 3,
'CC.D.E': 4,
'CC.D.F': 5
}
实现将其转换为 “”嵌套“” 字典对象的功能。
在上述情况下,嵌套版本如下:
{
'A': 1,
'B': {
'A': 2,
'B': 3
}
'CC': {
'D': {
'E': 4,
'F': 5
}
}
}
确保字典中任何的键都不是其他键的前缀。
给定一个整数数组
[6, 4, -3, 5, -2, -1, 0, 1, -9]
,实现一个函数,将所有正数向左一定,并将所有负数向右移动。
尽力将其时间复杂度设为O(n),并将空间复杂度设为O(1)。
[
["a", "aa", "aaa", "aaaa"],
["b", "bb", "bbb"],
["a", "ab", "aba"],
["a", "aa", "aab"]
] 转为:
[
{
"name" : "a",
"child" : [
{
"name" : "aa",
"child" : [
{
"name" : "aaa",
"child" : [
{
"name" : "aaaa",
"child" : []
}
]
},
{
"name" : "aab",
"child" : []
}
]
},
{
"name" : "ab",
"child" : [
{
"name": "aba",
"child" : []
}
]
}
]
},
{
"name": "b",
"child" : [
{
"name" : "bb",
"child" : [
{
"name" : "bbb",
"child" : []
}
]
}
]
}
]
需要对上传的图片进行压缩,要求图片总像素不大于 400(20 20),
假如输入一张 3080 的图片,问长边应该压缩到多少,如何计算?
'use strict'
// 编写一段函数,将一个对象某一个层级中与指定键相同的键值赋值到第二个对象某一层级中有相同键的值。
// 例如:
// input
const tree1 = {
aa: {
bb: {
cc: '123'
}
}
}
const tree2 = {
0: {
id: 0,
aa: {
oo: 89,
bb: {
cc: null
}
}
},
1: {
id: 1,
aa: {
oo: 84,
bb: {
cc: null
}
}
}
}
const key = 'cc'
// output
const tree2 = {
0: {
id: 0,
aa: {
oo: 89,
bb: {
cc: '123'
}
}
},
1: {
id: 1,
aa: {
oo: 84,
bb: {
cc: '123'
}
}
}
}
根据W3C性能小组的介绍,超过50ms的任务就是长任务。
图片来自使用 RAIL 模型评估性能
根据上图我们可以知道,当延迟超过100ms,用户就会察觉到轻微的延迟。
所以为了避免这种情况,我们可以使用两种方案,一种是Web Worker,另一种是时间切片(Time Slicing)。
我们都知道,JS是单线程,所以当我们在运行长任务时,容易造成页面假死的状态,虽然我们可以将任务放在任务队列中,通过异步的方式执行,但这并不能改变JS的本质。
所以为了改变这种现状,whatwg推出了Web Workers。
具体的语法不会进行说明,有兴趣的童鞋可以查看MDN Web Worker。
我们可以看看使用了Web Worker
之后的优化效果:
const testWorker = new Worker('./worker.js')
setTimeout(_ => {
testWorker.postMessage({})
testWorker.onmessage = function (ev) {
console.log(ev.data)
}
}, 5000)
// worker.js
self.onmessage = function () {
const start = performance.now()
while (performance.now() - start < 1000) {}
postMessage('done!')
}
代码以及截图来自于让你的网页更丝滑
时间切片是一项使用得比较广的技术方案,它的本质就是将长任务分割为一个个执行时间很短的任务,然后再一个个地执行。
这个概念在我们日常的性能优化上是非常有用的。
例如当我们需要在页面中一次性插入一个长列表时(当然,通常这种情况,我们会使用分页去做)。
如果利用时间分片的概念来实现这个功能,我们可以使用requestAnimationFrame
+DocumentFragment
关于这两个API,我同样不会做详细的介绍,有兴趣的可以查看MDN requestAnimationFrame跟MDN DocumentFragment。
这里有两个DEMO,大家可以对比下流畅程度:
未使用时间分片:
<style>
* {
margin: 0;
padding: 0;
}
.list {
width: 60vw;
position: absolute;
left: 50%;
transform: translateX(-50%);
}
</style>
<ul class="list"></ul>
<script>
'use strict'
let list = document.querySelector('.list')
let total = 100000
for (let i = 0; i < total; ++i) {
let item = document.createElement('li')
item.innerText = `我是${i}`
list.appendChild(item)
}
</script>
使用时间分片:
<style>
* {
margin: 0;
padding: 0;
}
.list {
width: 60vw;
position: absolute;
left: 50%;
transform: translateX(-50%);
}
</style>
<ul class="list"></ul>
<script>
'use strict'
let list = document.querySelector('.list')
let total = 100000
let size = 20
let index = 0
const render = (total, index) => {
if (total <= 0) {
return
}
let curPage = Math.min(total, size)
window.requestAnimationFrame(() => {
let fragment = document.createDocumentFragment()
for (let i = 0; i < curPage; ++i) {
let item = document.createElement('li')
item.innerText = `我是${index + i}`
fragment.appendChild(item)
}
list.appendChild(fragment)
render(total - curPage, index + curPage)
})
}
render(total, index)
</script>
没有做太多的测评,但是从用户视觉上的感受来看就是,第一种方案,我就是想刷新都要打好几个转,往下滑的时候也有白屏的现象。
除了上述的生成DOM的方案,我们同样可以利用Web Api requestIdleCallback
以及ES6 API Generator]
来实现。
同样不会做太多的介绍,详细规则可以看MDN requestIdleCallback以及MDN Generator。
具体实现如下:
<style>
* {
margin: 0;
padding: 0;
}
.list {
width: 60vw;
position: absolute;
left: 50%;
transform: translateX(-50%);
}
</style>
<ul class="list"></ul>
<script>
'use strict'
function gen(task) {
requestIdleCallback(deadline => {
let next = task.next()
while (!next.done) {
if (deadline.timeRemaining() <= 0) {
gen(task)
return
}
next = task.next()
}
})
}
let list = document.querySelector('.list')
let total = 100000
function* loop() {
for (let i = 0; i < total; ++i) {
let item = document.createElement('li')
item.innerText = `我是${i}`
list.appendChild(item)
yield
}
}
gen(loop())
</script>
实现一个Person类,类里有eat、work、sleep三个方法,支持如下调用方式eat().work(10).sleep(5)
打印结果为
eat()
eat()->work(10) //等待10后打印
eat()->work(10)->sleep(5) //等待5秒后打印
在网上看到这么一道题:
这道题跟鱼头这篇记录『什么是时间分片(Time Slicing)?』有点相似,但不同的是这次是限制异步并发的数量。
所以话不多说,我们先来康康实现
首先我们来实现一个分割数组的函数~
const group = (list = [], max = 0) => {
if (!list.length) {
return list
}
let results = []
for (let i = 0, len = list.length; i < len; i += max) {
results.push(list.slice(i, i + max))
}
return results
}
这里就是根据指定的并发数量来分割数组。主要就是for
+ slice
,这没啥好说的
接下来我们再来一个用async
+ await
实现的请求集合封装。
我们通Promise.allSettled
去执行每一组的请求集合。
Promise.allSettled
是一个新的API,跟Promise.all
差不多的用法,也是接受的数组,不过不同的是Promise.allSettled
会等所有任务结束之后才会返回结果,而Promise.all
只要有一个reject
就会返回结果。
const requestHandler = async (
groupedUrl = [],
callback = () => { }
) => {
if (!groupedUrl.length) {
callback()
return groupedUrl
}
const newGroupedUrl = groupedUrl.map(fn => fn())
const resultsMapper = (results) => results.map(callback)
const data = await Promise.allSettled(newGroupedUrl).then(resultsMapper)
return data;
}
接下来就是主函数
const sendRequest = async (
urls = [],
max = 0,
callback = () => { }
) => {
if (!urls.length) {
return urls
}
const groupedUrls = group(urls, max)
const results = []
console.log('start !')
for (let groupedUrl of groupedUrls) {
try {
const result = await requestHandler(groupedUrl, callback)
results.push(result)
console.log('go')
} catch { }
}
console.log('done !')
return results
}
这里就是利用了for
+ async
+ await
来限制并发。等每次并发任务结果出来之后再执行下一次的任务。
我们执行下栗子:
const p1 = () => new Promise((resolve, reject) => setTimeout(reject, 1000, 'p1'))
const p2 = () => Promise.resolve(2)
const p3 = () => new Promise((resolve, reject) => setTimeout(resolve, 2000, 'p3'))
const p4 = () => Promise.resolve(4)
const p5 = () => new Promise((resolve, reject) => setTimeout(reject, 2000, 'p5'))
const p6 = () => Promise.resolve(6)
const p7 = () => new Promise((resolve, reject) => setTimeout(resolve, 1000, 'p7'))
const p8 = () => Promise.resolve(8)
const p9 = () => new Promise((resolve, reject) => setTimeout(reject, 1000, 'p9'))
const p10 = () => Promise.resolve(10)
const p11 = () => new Promise((resolve, reject) => setTimeout(resolve, 2000, 'p10'))
const p12 = () => Promise.resolve(12)
const p13 = () => new Promise((resolve, reject) => setTimeout(reject, 1000, 'p11'))
const p14 = () => Promise.resolve(14)
const ps = [p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14]
sendRequest(ps, 3, ({reason, value}) => {
console.log(reason || value)
})
OK,我们看到结果是如我们所愿的
问题如下:
let input = [
{ id: '17', caption: '颜色', types: ['黑', '棕'] },
{ id: '23', caption: '材质', types: ['牛皮'] },
{ id: '24', caption: '尺码', types: ['40', '41', '42'] }
]
let output = [
{ "17": "黑", "23": "牛皮", "24": "40" },
{ "17": "黑", "23": "牛皮", "24": "41" },
{ "17": "黑", "23": "牛皮", "24": "42" },
{ "17": "棕", "23": "牛皮", "24": "40" },
{ "17": "棕", "23": "牛皮", "24": "41" },
{ "17": "棕", "23": "牛皮", "24": "42" }
]
一道排列组合题,也挺有意思的,有兴趣的可以来回答一波
A、 B 、 C 是 3 个字符串。把 A 中包含的所有 B 都替换为 C ,如果替换以后还有 B 就继续替 换,直到 A 不包含 B 为止。
例:
[2, 6]、[1, 4]、[5, 8]
交集为:
[2, 4]、[5, 6]
注:
第一个解的意思是 [2, 6]、[1, 4]
的区间为[2, 4]
第二个解的意思是 [2, 6]、[5, 8]
的区间为[5, 6]
R.T
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.