前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >个人笔记(js+css篇二)

个人笔记(js+css篇二)

作者头像
y191024
发布2022-12-29 14:39:29
3830
发布2022-12-29 14:39:29
举报

事件循环

所有任务可以分成两种,一种是同步任务(synchronous),另一种是异步任务(asynchronous)。同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;异步任务指的是,不立即进入主线程、而先进入"任务队列"(task queue)的任务,只有"任务队列"通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。

任务队列

"任务队列"是一个先进先出(队列)的数据结构,排在前面的事件,优先被主线程读取。任务队列又分为宏队列和微队列,分别存放宏任务和微任务。

在JavaScript中,任务被分为两种,一种宏任务(MacroTask),一种叫微任务(MicroTask)

常见的宏任务:

script全部代码、setTimeout、setInterval

常见的微任务:

Promise中then的回调函数、MutationObserver、Process.nextTick

事件循环过程

(1) js代码执行时,先按代码顺序将同步任务压入主执行栈中执行

(2) 遇到异步任务则先将异步任务压入对应的任务队列中(宏队列或微队列)

(3) 同步任务执行完毕后,查看微队列,将微任务一一取出进入主执行栈中执行

(4) 微任务队列清空后,再查看宏队列,只取出第一个宏任务执行,执行完一个宏任务后,回到第三步的操作。

这个过程是循环不断的,所以整个的这种运行机制又称为Event Loop(事件循环)。(需要注意的点就是then中的回调函数要确定Promise状态后才能压入微队列)

例1

这个还算简单吧!首先碰到new Promise,注意哦new Promise这一步是同步函数,.then才是异步的,所以直接打印出"Promise",接着碰到.then了,将这个任务放到微任务队列中的第一个,等同步全部执行完才能执行,接下来就是打印"Hi", 现在同步全部结束了,可以轮到微任务了。

最后的结果就是 Promise--> Hi! --> resolved

例2,加大难度吼

代码语言:javascript
复制

setTimeout(function () {
    console.log(1);
    
});
new Promise(function(resolve,reject){
    console.log(2)
    resolve(3);
 
}).then(function(val){
    console.log(val);
 
    new Promise((resolve, reject) => {
        console.log(5)
        resolve(7)
    }).then(res => {
        console.log(res);
    })
 
})
console.log(4);

一步一步来吧,这种要慢慢分析,因为同步里面又包裹了异步之类的。

①首先第一步看到setTimeOut,放入宏任务队列。

②随后是一个同步的newPromise函数,直接打印2。然后将里面的.then的异步微任务放入队列

③最后又是一个同步,打印4,此时的任务队列

接下来继续, 那么这个循环中的同步函数已经结束了,我们现在进入这个then的微任务中:

④里面的log(val)的val就是resolve过来的3哈,所以直接打印。

⑤接下来又是一个同步函数,打印出5,然后又遇到.then,放入队列。

此时的队列情况

⑥那么接下来又是开始微任务,很简单就一个log(res),就是7。

⑦最后最后就是定时器了,直接打印1。

所以最后的结果是

再来一个:

代码语言:javascript
复制
console.log(1); // 同步
setTimeout(() => {
// 定时器1
    console.log(2); // 同步
    Promise.resolve().then(() => {
    // 异步 定时器微任务
        console.log(3);
    })
    console.log(8);
})
new Promise((resolve, reject) => {
// 同步
    console.log(4);
    resolve(5);
}).then((data) => {
// 异步微任务1
    console.log(data);
})
setTimeout(() => {
// 记作定时器2 异步宏任务
    console.log(6);
})
console.log(7)

这次就不画图了,直接文字解答吧:

① 最开头不用多说,直接打印1

②接下来是定时器1,先不用管里面,直接丢宏任务队列1里。

③到了new Promise,是个同步的函数,将里面的4打印,然后又碰到了.then,放入异步微任务1

④又是一个定时器,不用管直接放宏任务队列2

⑤又是直接可以打印的,打印7


循环暂时告一段落,现在看微任务列表,只有一个异步微任务1

①异步微任务中打印出5

现在只剩下两个宏任务了,先看宏任务1。

①先打印出2

②下面又是一个微任务,放入定时器微任务队列

打印8

④来到定时器微任务队列,打印3 轮到最后一个宏任务队列,定时器2

打印6

如果还是不懂最后画一个图吧

再最后来一题吧、、复杂点,我就不写过程啦,不懂后台再问。

代码语言:javascript
复制
    console.log("1主线程"); //整体script作为第一个宏任务进入主线程
    setTimeout(function () {
      //setTimeout,其回调函数被分发到宏任务Event Queue(执行规则:从上到下排序,先进先执行)中
      console.log("2宏任务");
      nextTick(function () {
        console.log("3宏任务里面的微任务");
      });
      new Promise(function (resolve) {
        console.log("4微任务");
        resolve();
      }).then(function () {
        console.log("5微任务");
      });
    });
    /*nextTick(function () {  //改掉了这里是因为对nextTick有疑问,
    // 好像不完全是微任务...结果会有所不同。
      console.log("6微任务");
    }); */
    new Promise((resolve, reject) => {resolve()}).then(() => {
      console.log("6微任务");
    });
    new Promise(function (resolve) {
      //Promise,new Promise直接执行,输出7
      console.log("7微任务");
      resolve();
    }).then(function () {
      console.log("8微任务"); //then被分发到微任务Event Queue中,排在process.nextTick微任务后面。
    });
    setTimeout(function () {
      //setTimeout,其回调函数被分发到宏任务Event Queue中,排在前面的setTimeout后面
      console.log("9宏任务");
      nextTick(function () {
        console.log("10宏任务里面的微任务");
      });
      new Promise(function (resolve) {
        console.log("11微任务");
        resolve();
      }).then(function () {
        console.log("12微任务");
      });
    });

可以试一下嘻嘻,反正我会啦!

最后结果:

但是await需要注意一下。

我自己写一个

代码语言:javascript
复制
const fun = () => {
  console.log('我是function');
  
}
async function demo() {
  await fun()
  console.log('我是被阻塞的,会跳出async函数,在外部的同步函数执行完才会执行');
  
}
demo()
console.log('script结束');

最后的结果是什么呢:

进入demo函数后会照常执行后面的fun函数,但是发现前面是await,就会阻塞其所在表达式中后续表达式的执行,跳出async函数,执行外面的同步代码。

如果async关键字函数返回的不是promise,会自动用Promise.resolve()包装

如果async关键字函数显式地返回promise,那就以你返回的promise为准

如果不是 promise , await会阻塞后面的代码,先执行async外面的同步代码,同步代码执行完,再回到async内部,把这个非promise的东西,作为 await表达式的结果

如果它等到的是一个 promise 对象,await 也会暂停async后面的代码,先执行async外面的同步代码,等着 Promise 对象 fulfilled,然后把 resolve 的参数作为 await 表达式的运算结果。

放一道经典的面试题吧(今日头条面试题)

代码语言:javascript
复制
  async function async1() {
        console.log( 'async1 start' )
        await async2()
        console.log( 'async1 end' )
    }
    
    async function async2() {
        console.log( 'async2' )
    }
    
    console.log( 'script start' )
    
    setTimeout( function () {
        console.log( 'setTimeout' )
    }, 0 )
    
    async1();
    
    new Promise( function ( resolve ) {
        console.log( 'promise1' )
        resolve();
    } ).then( function () {
        console.log( 'promise2' )
    } )
    
    console.log( 'script end' )

分析过程

但是要注意不同的浏览器执行起来结果可能有所不同,我使用的是谷歌浏览器

最后再来一个测试一下学会了没有吧:

代码语言:javascript
复制
async function async1() {
    console.log( '1' )
    console.log(await async2())
    console.log( '2' )
}
async function async2() {
    console.log('3')
    setTimeout(
      ()=>console.log('4')
    ,0)
    console.log( '5' )
}
console.log( '6' )
setTimeout( function () {
    console.log( '7' )
}, 0 )
async1();
new Promise( function ( resolve ) {
    console.log( '8' )
    resolve();
} ).then( function () {
    console.log( '9' )
} )
console.log( '10' )

结果:

注意这个undefined哈,因为是log await的结果,但是resolve里面没有传递参数,所以就相当于是resolve(undefined),打印出来就是undefined。

本文由“壹伴编辑器”提供技术支持

flex布局

想不到吧这玩意我都忘得差不多了...重新学下,主要是吧用的时候总是不生效,都要疯了

注意:当设置 flex 布局之后,子元素的 float、clear、vertical-align 的属性将会失效。

有下面六种属性可以设置在容器上,它们分别是:

  • flex-direction
  • flex-wrap
  • flex-flow
  • justify-content
  • align-items
  • align-content

1. flex-direction: 决定主轴的方向(即项目的排列方向)

设置在父元素的样式上

代码语言:javascript
复制
.container {
    flex-direction: row | row-reverse | column | column-reverse;
}

默认的方向: row,主轴为水平方向,起点在左端。

row-reverse: 起点在右端

column: 主轴为垂直方向,起点在上方

column-reverse:

本文由“壹伴编辑器”提供技术支持

2. flex-wrap: 决定容器内项目是否可换行

默认情况下,项目都排在主轴线上,使用 flex-wrap 可实现项目的换行。

代码语言:javascript
复制
.container {
    flex-wrap: nowrap | wrap | wrap-reverse;
}

默认值:nowrap 不换行,即当主轴尺寸固定时,当空间不足时,项目尺寸会随之调整而并不会挤到下一行。

此时虽然给li设置了宽度,但是也无效了

wrap:项目主轴总尺寸超出容器时换行,第一行在上方

不设置宽度的话wrap也不会生效,因为 不知道怎么换行

因为每个li的宽度为500,屏幕放不下

本文由“壹伴编辑器”提供技术支持

3. justify-content:定义了项目在主轴的对齐方式。

代码语言:javascript
复制
.container {
    justify-content: flex-start | flex-end | center | space-between | space-around;
}

默认值: flex-start 左对齐

注意哈,没有设置flex:1,只设置了宽度,而且宽度不能大到让四个在一行放不下,因为默认不换行,会四个均分宽度,就不会靠左或者靠右了

就是这个意思。

flex-end:右对齐 end也是可以的哈

center:居中

space-between:两端对齐,项目之间的间隔相等,即剩余空间等分成间隙。

space-around:每个项目两侧的间隔相等,所以项目之间的间隔比项目与边缘的间隔大一倍。

本文由“壹伴编辑器”提供技术支持

5. align-items: 定义了项目在交叉轴上的对齐方式

代码语言:javascript
复制
.container {
    align-items: flex-start | flex-end | center | baseline | stretch;
}

建立在主轴为水平方向时测试,即 flex-direction: row

默认值为 stretch 即如果项目未设置高度或者设为 auto,将占满整个容器的高度。

注意li不要设置高度,否则高度不会变。

flex-start:交叉轴的起点对齐

此时将li的高度分别设置为25px, 50px, 75px 100px。

flex-end:交叉轴的终点对齐

center:交叉轴的中点对齐

我用的话基本也就这些,其他的用到了再说。

本文由“壹伴编辑器”提供技术支持

今天在写的时候又发现一个知识,就是怎么让ul的长度随着li的长度而变化,那就是加上属性 width: fit-content,就可以啦

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-12-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 睡不着所以学编程 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档