HTML

从输入 URL 到页面加载完成,发生了什么?

  1. 浏览器根据 DNS 服务器得到域名的 IP 地址

    • DNS:负责解析域名,返回正确的IP。
    • DNS的用法:A解析,CNAME解析
    • DNS污染
  2. 向这个 IP 的机器建立TCP连接
  3. 向服务器发送 HTTP 请求
  4. 服务器收到、处理并返回 HTTP 请求
  5. 浏览器得到返回内容
  6. 浏览器渲染页面

    • 根据 HTML 结构生成 DOM 树
    • 根据 CSS 生成 CSSOM
    • 将 DOM 和 CSSOM 整合形成 RenderTree
    • 根据 RenderTree 开始渲染和展示
    • 遇到<script>时,会执行并阻塞渲染

为何要将 CSS 放在 HTML 头部?为何要将 JS 放在 HTML 底部?

这样会让浏览器尽早拿到 CSS 尽早生成 CSSOM,然后在解析 HTML 之后可一次性生成最终的 RenderTree,渲染一次即可。如果 CSS 放在 HTML 底部,会出现渲染卡顿的情况,影响性能和体验。

渲染过程中,如果遇到<script>就停止渲染,执行 JS 代码。因为浏览器渲染和 JS 执行共用一个线程,而且这里必须是单线程操作,多线程会产生渲染 DOM 冲突。待<script>内容执行完之后,浏览器继续渲染。

JS 放在底部可以保证让浏览器优先渲染完现有的 HTML 内容,让用户先看到内容,体验好。另外,JS 执行如果涉及 DOM 操作,得等待 DOM 解析完成才行,JS 放在底部执行时,HTML 肯定都解析成了 DOM 结构。JS 如果放在 HTML 顶部,JS 执行的时候 HTML 还没来得及转换为 DOM 结构,可能会报错。

DOM 和 HTML 区别和联系

DOM BOM 和XML

DOM,全称Document Object Model。DOM的本质(MDN里写的很明确了)是API。树形数据结构的XML和HTML,符合DOM规范,就能被DOM API操作。

树形结构是属于XML和HTML等这样结构化的东西,DOM只是提供一种方法去操纵他。

什么是HTML语义化

不要滥用<div>标签,而是转而使用<section> <header> <foter> <nav> <article> <main>去

  • 增加代码的可读性
  • 减少系统开发的时候class的冲突

Meta viewpoint作用

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no" />

这段代码的意思是,让viewport的宽度等于物理设备上的真实分辨率,不允许用户缩放。

CSS

基础知识:常见选择器

通配符选择器

* {
  color: blue;
}

元素选择器

p {
  color: blue;
}

类选择器

生效的html的部分:

<p class="myStyle"> This is some random shit</p>

<p> something inside <span class="myStyle">in this p tag</span> here.</p>

css部分:

*.myStyle {
  color:  #fff;
}

/*等同于:*/
.myStyle {
  background-image: #000;
}

这就是说属于myStyle类的元素 都会生效。例如,DOM树中的p.warningspan.warning都会生效。注意类选择器可以对页面中任意多的元素生效。

ID选择器

对DOM树中特定ID的元素生效。和类选择器不同,ID在一个HTML文档里仅使用一次

<p id="myDOM"> this is a text</p>

css部分:

*#myDOM{
  /*something*/
}
#myDOM {
  font-weight: bold;
}

基础知识:属性选择器

简单属性选择器

选择带有某种属性的元素。无视具体属性的值

h1[class]{
  font-weight: bold;
}
<h1 class="myClass">本元素会被选中</h1>
<h1> 本元素不会被选中</h1>
<h1 class="myClass2"> 虽然class不同,但是仍然具有class属性 所以也会被选中</h1>

准确属性选择器

选择带有某种属性、且值为规定值的元素。

<planet>mars</planet>
<planet star="1">earth</planet>
<planet star="2">moon</planet>
planet[star="1"]{
  font-weight: bold;
}

只有有star属性为1的planet标签被选中。

部分属性选择器

使用文档DOM结构帮助选择元素

后代选择器和子选择器

a b{
  /*选择b元素,且b元素必须为a的后代*/
}

a > b{
  /*选择b元素,且b必须是a的子元素*/
}

相邻兄弟选择器和一般兄弟选择器

h1+p{
  /*选择前一个元素正好是h1元素的p元素*/
  /*
  * h1 p p h1 p 
  *      ↑      ↑
  */
}

h1~p {
  /*选择*/
  /*
  * h1 p p h1 p 
  *      ↑ ↑    ↑
  */
}

选择器的权重和优先级

权重分为四级,分别是:

  1. 代表内联样式,如style="xxx",权值为 1,0,0,0;
  2. 代表 ID 选择器,如#content,权值为 0,1,0,0;
  3. 代表类、伪类和属性选择器,如.content:hover[attribute],权值为 0,0,1,0;
  4. 代表元素选择器和伪元素选择器,如divp,权值为0,0,0,R1。

盒模型

img

  • margin 外边距
  • border 盒子边距
  • padding 内边距

在盒子模型中,我们设置的宽度都是内容宽度,不是整个盒子的宽度。而整个盒子的宽度是:(内容宽度 + border宽度 + padding宽度 + margin宽度)之和

BFC IFC FFC

BFC

BFC的全称是 Block Formatting Contexts。可以建议的理解为为块级元素创造一个独立的空间。

1、内部的块级元素会在垂直方向,一个接一个地放置。

2、块级元素垂直方向的距离由margin决定。属于同一个BFC的两个相邻块级元素的margin会发生重叠。

3、对于从左往右的格式化,每个元素(块级元素与行内元素)的左边缘,与包含块的左边缘相接触,(对于从右往左的格式化则相反)。即使包含块中的元素存在浮动也是如此,除非其中元素再生成一个BFC。

4、BFC的区域不会与浮动元素重叠。

5、BFC是一个隔离的独立容器,容器里面的子元素和外面的元素互不影响。

6、计算BFC容器的高度时,浮动元素也参与计算。

BFC的触发条件
  • float不为none
  • position不为relative或static
  • overflow为auto , scroll 或hidden
  • display的值为table-cell 或者inline-block
BFC能解决的问题
  1. 清除浮动(请见下方清除浮动小节)
  2. 解决自适应布局问题

    • 方法1:左浮动固定宽,右边marginleft=左宽
    • 方法2:左绝对定位(position absolute, top/left/bottom 0)定宽,右边marginleft=左宽
    • 方法3:父元素flex,左最小宽度固定
      image-20200506115702579
  3. 解决兄弟元素之间margin取最大值而不是求和的问题

    • 方法1:设置margin-bottom,同时设置padding-top (取代margin-top)
    • 方法2:为其中一个子元素(例如下面的)包一层父元素并设置 {overflow: hidden}触发BFC
      image-20200506120045705

实战应用:居中对齐

水平居中

.container {
    text-align: center;
}
.container{
    text-align: center;
}
.item {
    width: 1000px;
    margin: 0 auto /*mdn推荐写法*/
}

垂直居中

全页面垂直居中(不知道宽高)
/*全页面垂直居中*/
.text {
 position:absolute;
 left: 50%; //移动到父级的50%
 top: 50%; 
 transform: translate(-50%,-50%);
}

image-20200505171109358

绝对定位(知道宽高)
div{
    width:600px;
    height:600px;
    position: absolute;
    /*begin*/
    left:50%;
    top;50%;
    margin-left: -300px;
    margin-top: -300px;
}

这个很好理解,通过left和top位移到中心,然后通过更改子元素的margin来移动位置,其中margin值需要通过父元素的值来计算。

绝对定位二
div.child{
    width: 600px;
    height: 600px;
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    right: 0;
    margin: auto;
}
使用FLEX垂直居中
.box{
    display: flex;
    align-items: center;
    justify-content: center;
}
child {
    /*foo bar*/
}

清除浮动

什么是浮动

被使用了float属性的元素,但是由于float的破坏性,导致被设置了float的元素脱离了文档流。

float的两个特性:

  • 包裹性:给<div>设置了float之后,他的宽度会自动调整为包裹住内容的宽度,而不是撑起父容器。
  • 清空格:对于一个正常的<div>容器,里面的img元素因为换行,元素之间会有空格。但是为div增加float属性后,空格消失,元素浮动溢出。根本原因是 float 会导致节点脱离文档流结构。它都不属于文档流结构了,那么它身边的什么换行、空格就都和它没了关系,它就尽量往一边靠拢,能靠多近就靠多近,这就是清空格的本质。
手写清除浮动的代码clearfix
.clearfix::after {
    content: '';
    display: table;
    /*关键*/
    clear: both;
    /*非必须*/
    visibility: hidden; 
    height: 0;
}
.clearfix {
    *zoom: 1; /* 兼容 IE 低版本 */
}

使用:

<div class="clearfix">
     <img src="img/1.png" style="float: left"/>
     <img src="img/2.png" style="float: left"/>
</div>

clear是CSS中的定位属性,规定元素的哪一侧不允许其他浮动元素。那么clear:both就是规定在左右两侧均不允许浮动元素。

clear属性只能在块级元素上其作用,这就是清除浮动样式中display:block的作用。

另外visibility: hidden;height: 0;只要content的值为空。写不写都无所谓。

为了显示清楚一点,在.wrap:after 样式中的content设置为content: 'after伪元素' ,此时如下图所示。

img

随后在.wrap:after 样式中加上clear:both,表明after伪元素左右两侧均不允许浮动元素,没办法只好把after伪元素放在下面,此时如下图所示。

img

image-20200506115525817

顺带撑起了.wrap父元素的高度,这样就相当清除了浮动了,解决了外层容器高度坍塌的问题。

那么我们把.wrap:after 样式中的content设置为content:' ',最后就如下图所示。

img

CSS动画

使用left和translateX的效果是一样的吗

不推荐使用left,这会额外触发layout与paint,而translate只会整个页面composite

具体的触发见下表:

image-20200506225600610

JS

ECMA Script

JS的语言标准,严格来说也是很多语言的标准。诞生于1995年,1999年出现ES3,2009年出现ES5,2015年出现ES6,所以ES6也称ES2015。ES6的目标是编写大型应用程序,成为企业级开发语言。

jQuery的语法是偏向于ES3的,主流前端开发框架使用的是ES6+

ECMA的阶段:语法提案的批准流程

任何人都可以向标准委员会(又称 TC39 委员会)提案,要求修改语言标准。

一种新的语法从提案到变成正式标准,需要经历五个阶段。每个阶段的变动都需要由 TC39 委员会批准。

  • Stage 0 - Strawman(展示阶段)
  • Stage 1 - Proposal(征求意见阶段)
  • Stage 2 - Draft(草案阶段)
  • Stage 3 - Candidate(候选人阶段)
  • Stage 4 - Finished(定案阶段)

一个提案只要能进入 Stage 2,就差不多肯定会包括在以后的正式标准里面。

ES5的特性

  • foreach
  • Object.keys
  • Object.create
  • json标准

ES6的新特性

  • let和const
  • 变量解构赋值
  • symbol
  • set和map数据结构
  • 代理(proxy) 也就是getter和setter
  • promise对象
  • Iterator
  • Generator
  • async函数
  • Class
  • Module

变量类型

Boolean ,String, Number,Null,Undefined,Symbol,没有Object

typeofinstanceof:类型判断的方法

  • typeof null结果是object ,实际这是typeof的一个bug,null是原始值,非引用类型
  • typeof [1, 2]结果是object,结果中没有array这一项,引用类型除了function其他的全部都是object

原型链

Prototype__proto__

所有的引用类型:数组、对象、函数,都具有对象特性(可以自由拓展属性):

// 要点一:自由扩展属性
var obj = {}; obj.a = 100;
var arr = []; arr.a = 100;
function fn () {}
fn.a = 100;

都有一个__proto__属性,属性值是一个普通对象,指向它构造函数的prototype属性。

值类型传递和共享类型传递

按值

变量提升 作用域 闭包

var let const 和变量提升es6新特性

const声明创建一个值的只读引用。但这并不意味着它所持有的值是不可变的,只是变量标识符不能重新分配。例如,在引用内容是对象的情况下,这意味着可以改变对象的内容(例如,其参数)。

变量提升

在一段 JS 脚本(即一个<script>标签中)执行之前,要先解析代码(所以说 JS 是解释执行的脚本语言),解析的时候会先创建一个 全局执行上下文 环境,先把代码中即将执行的(内部函数的不算,因为你不知道函数何时执行)变量、函数声明都拿出来。由于变量声明(以及其他声明)总是在任意代码执行之前处理的,所以在代码中的任意位置声明变量总是等效于在代码开头声明。这意味着变量可以在声明之前使用,这个行为叫做“hoisting”。“hoisting”就像是把所有的变量声明移动到函数或者全局代码的开头位置。变量先暂时赋值为undefined,函数则先声明好可使用。这一步做完了,然后再开始正式执行程序。再次强调,这是在代码执行之前才开始的工作。

实际 JS 在代码执行之前,要「全文解析」,发现var a,知道有个a的变量,存入了执行上下文,而b没有找到var关键字,这时候没有在执行上下文提前「占位」,所以代码执行的时候,提前报到的a是有记录的,只不过值暂时还没有赋值,即为undefined,而b在执行上下文没有找到,自然会报错(没有找到b的引用)。

console.log(a)  // undefined
var a = 100

console.log(b); // 这里报错
// Uncaught ReferenceError: b is not defined
b = 100;

变量提升的深入认识

JS 变量声明有三步

  • 创建create
  • 初始化initialize (为undefined
  • 赋值assign

let 到底有没有提升:

  1. let 的「创建」过程被提升了,但是初始化没有提升。
  2. var 的「创建」和「初始化」都被提升了。
  3. function 的「创建」「初始化」和「赋值」都被提升了。

最后看 const,其实 const 和 let 只有一个区别,那就是 const 只有「创建」和「初始化」,没有「赋值」过程。

img

假设有如下代码:

function fn(){
  var x = 1
  var y = 2
}
fn()

在执行 fn 时,会有以下过程(不完全):

  1. 进入 fn,为 fn 创建一个环境。
  2. 找到 fn 中所有用 var 声明的变量,在这个环境中「创建」这些变量(即 x 和 y)。
  3. 将这些变量「初始化」为 undefined。
  4. 开始执行代码
  5. x = 1 将 x 变量「赋值」为 1
  6. y = 2 将 y 变量「赋值」为 2

也就是说 var 声明会在代码执行之前就将「创建变量,并将其初始化为 undefined」。

这就解释了为什么在 var x = 1 之前 console.log(x) 会得到 undefined。

这就解释了为什么在 let x 之前使用 x 会报错:

let x = 'global'
{
  console.log(x) // Uncaught ReferenceError: x is not defined
  let x = 1
}

原因有两个

  1. console.log(x) 中的 x 指的是下面的 x,而不是全局的 x
  2. 执行 log 时 x 还没「初始化」,所以不能使用(也就是所谓的暂时死区)

作用域 和作用域链

作用域

块级作用域是ES6的新特性。JS 没有块级作用域,只有全局作用域和函数作用域。

if (true) {
    var name = 'zhangsan'
}
console.log(name) // zhangsan

// 这里说明没有块级作用域。这里的变量name泄露出去了

这非常容易造成变量污染,试想:

// 小明的代码
var data = {a:100};

// 小红的代码
var data = {b:100};

所以通常情况下都利用函数作用域来包裹变量,(function(){....})()

ES6中加入了块级作用域

if (true) {
    let name = 'zhangsan'
}
console.log(name) // 报错 ReferenceError: name is not defined

// 因为let定义的name是在if这个块级作用域
作用域链

在每个变量作用域依次往上寻找变量声明,如果全局作用域都没找到,就宣布放弃

var a = 100
function F1() {
    var b = 200
    function F2() {
        var c = 300
        console.log(a) // 自由变量,顺作用域链向父作用域找
        console.log(b) // 自由变量,顺作用域链向父作用域找
        console.log(c) // 本作用域的变量
    }
    F2()
}
F1()

闭包(Closure)

闭包的概念

函数可以访问到其他作用域的变量,但是函数本身的变量又不被泄露出来,被称为闭包。

MDN解释:

函数和对其周围状态(lexical environment,词法环境)的引用捆绑在一起构成闭包closure)。也就是说,闭包可以让你从内部函数访问外部函数作用域。在 JavaScript 中,每当函数被创建,就会在函数生成时生成闭包。

function hd(){
    let n = 1;
    return function sum(){
        console.log(++n); // sum函数成功取到了函数外(复函数的作用域)的变量
    };
}
let a = hd(); // 这里执行hd()时,创建的sum()函数实例引用,这个实例维持了对他词法环境的引用(n被保留下来了)
a();
a();
// 输出:
// 2
// 3
闭包的应用

css

body {
  font-family: Helvetica, Arial, sans-serif;
  font-size: 12px;
}

h1 {
  font-size: 1.5em;
}

h2 {
  font-size: 1.2em;
}

目标:点击按钮修改body元素的font-size

const makeSizer = (size) => {
    return function(){
        document.body.style.fontSize = size + 'px';
    };
}

/* now change some size */
document.getElementById('size-12').onclick = makeSizer(12);
闭包模拟私有方法
let Counter = (function(){
    let privateCounter = 0 ;
    function changeBy(val){
        privateCounter += val;
    }
    return {
        increment: function(){
            changeBy(1);
        },
       decrement: function(){
           changeBy(-1);
       },
       getValue: function(){
           return privateCounter;
       }
    }
})();

this指向哪里?

分全局环境和函数环境。

无论是否在严格模式下,在全局执行环境中(在任何函数体外部)this 都指向全局对象。(可以用globalThis强制指向全局)

在浏览器中就是window,在node中就是global

在函数中,取决于函数被调用的方式

map filter reduce

map:该函数会遍历该数组,对每一个元素做变换之后返回新数组。

let arr = [1,2,3];
const arr2 = arr.map((element,index)=>{
    return `No.${index} : ${element}`;
})

filter:生成一个数组,传入的函数返回值确实布尔类型,返回值为 true 的元素放入新数组,通常来筛选删除不需要的元素。

let arr = [1,2,3];
const arr2 = arr.filter((element)=>{
    return element != 6;
})

reduce 可以将数组中的元素通过回调函数最终转换为一个值。

let arr = [1,2,3];
const arr2 = arr.reduce((acc,element)=>{
    return acc+element;
})

PROXY(GETTER & SETTER)

class person {
    constructor(){
        // 这里反而不能用 super();
        this.name='xiaolu'
    }
    
    get first
}

JS多线程

JS内核是单线程的

JS多线程

浏览器常驻三大线程: js引擎线程,GUI渲染线程,浏览器事件触发线程。浏览器是一个多线程的执行环境,在浏览器的内核中分配了多个线程,最主要的线程之一即是js引擎的线程,同时js事件队列中的异步请求,交互事件触发,定时器等事件都是由浏览器的事件触发线程进行监听的,浏览器的事件触发线程被触发后会把任务加入到js 引擎的任务队列中,当js 引擎空闲时候就会开始执行该任务

回调函数

Google的官方解释:

A callback is a function that is passed as an argument to another function and is executed after its parent function has completed.

回调函数是被另一个函数当作参数使用的函数,并且在他的父函数执行完毕时才会被执行

回调函数是JavaScript里约定俗成的一个名称。实际上并不存在确定的“回调函数”,只是大家就管那个位置的函数作回调函数。与大多数运行后立刻给出结果的函数不同,使用回调的函数要花一些时间才能得出结果。“异步”这个词就是代表‘要花时间,将来运行’。通常回调函数会用在下载文件、读取文件、或者数据库相关事务等。

当你调用一个普通函数,你可以立刻得到它的值:

const result = multyply(5,10);
console.log(rusult) // get 50

同步回调的函数的例子:

// 定义函数及回调函数
function validateUser( prams, callback){ //令第二个参数为回调参数
    let data = parse(prams);
    typeof(callback)==='function' && callback(data);
    // 意思是判断callback参数是不是function,并且执行callback(data);
       // 这种写法可以使用promise 替代
}

//调用回调函数
validateUser(user,(nodes)=>{
    //这里使用ES6箭头函数作为回调函数 充当一个参数 
       playWith(nodes)
})

所以回调与同步、异步并没有直接的联系,回调只是一种实现方式,既可以有同步回调,也可以有异步回调,还可以有事件处理回调和延迟函数回调,这些在我们工作中有很多的使用场景。

回调地狱

指的是回调的{}不断嵌套,导致可读性急剧下降

// Node.js是非阻塞编程,那么在编码过程中会遇到很多的回调函数
// (Callback),如果多个处理的回调函数嵌套在一起的话,
function dbupd(sql, done){
    //模拟一下数据库的更新时延
    setTimeout(() => done(sql + "upd ok."), 800);
}

//以下就是一个层层嵌套的“地狱”,反复回调
dbupd("1.sql1 ", result =>{
    console.log(result);
    dbupd("2.sql2 ", result =>{
        console.log(result);
        dbupd("3.sql3 ", result =>{
            console.log(result);
        });
    });
});
// 就会形成回调地狱,虽然对于程序的结果没有任何影响
// 但对于程序代码的可读性来说就是个地狱。

解决回调地狱

方法1:减少匿名函数和函数嵌套
  • 有了函数名,可以很容易知道这段代码的作用
  • 在控制台调试出错的时候,控制台会告诉你是哪个函数出错了,而不是一个匿名函数(anonymous)
  • 可以让你把这些函数移动到合适的位置,使用的时候用函数名调用就可以了
/*
* BAD
*/


var form = document.querySelector('form')
form.onsubmit = function formSubmit (submitEvent) {
  var name = document.querySelector('input').value
  request({
    uri: "http://example.com/upload",
    body: name,
    method: "POST"
  }, function postResponse (err, response, body) {
    var statusMessage = document.querySelector('.status')
    if (err) return statusMessage.value = err
    statusMessage.value = body
  })
}

/*
* GOOD
*/
document.querySelector('form').onsubmit = formSubmit

function formSubmit (submitEvent) {
  var name = document.querySelector('input').value
  request({
    uri: "http://example.com/upload",
    body: name,
    method: "POST"
  }, postResponse)
}

function postResponse (err, response, body) {
  var statusMessage = document.querySelector('.status')
  if (err) return statusMessage.value = err
  statusMessage.value = body
}
方法2:模块化

loader.js:

module.exports.submit = formSubmit //仅仅导入formsubmit模块

function formSubmit (submitEvent) {
  var name = document.querySelector('input').value
  request({
    uri: "http://example.com/upload",
    body: name,
    method: "POST"
  }, postResponse)
}

function postResponse (err, response, body) {
  var statusMessage = document.querySelector('.status')
  if (err) return statusMessage.value = err
  statusMessage.value = body
}

功能实现:数组去重

  1. es6最好用的方法:set

set这个数据结构就是集合,不会保存重复的值

function unique (arr) {
  return Array.from(new Set(arr))
}

unique(myArray)
  1. map
  2. es5常用方法:双层循环,如果发现了重复的 就用spice删除这个元素

Webpack

Webpack核心概念

HappyPack

Babel

DllPlugin

TreeShaking

前端框架

MVC和MVVM

Redux

redux是一种框架,并非React才能用。react-redux才是专门给react用的

核心思想是想state集中储存,

综合知识和经典面试问题

一分钟自我介绍

XXX经理您好,我叫XXX,你可以叫我xx。我毕业于一所武汉的一本高校,曾经在朋友的一家独立创业公司任职运营的工作,后来逐渐被安排了维护网络服务器和管理的工作。在此期间,我深深感到在前端方面的技术储备不足,想要在这方面多多学习进步,所以决定从事相关工作。XX公司

我认为我的优势主要有三方面:

  • 有很强的组织和协调能力。我能连接多个领域的知识和人员综合起来,协同大家工作,当过客服非常有耐心。英语能力也不错
  • 学习比较主动,习惯自己去查文档资料。
  • 责任意识非常强,对解决问题有很强的愿望。

2020年05月07日 面试点评:

  • 一开始就要做全栈,野心太大
  • 兴趣爱好太多 不适合做前端技术 静不下心来

为什么要前后端分离?

为了将前端部分的工作从后端中解耦,实现低耦合,高内聚,并且将视图构建的工作工程化、组件化。

  • 所谓 低耦合,试想很早以前所有开发者用的都是jsp,那个时候前后端的代码混合在一起,给协作带来了巨大的不便。解除耦合就是将后端开发者从前端开发中解脱出来。
  • 所谓 高内聚,是指前端和后端的内部功能高度凝聚,功能的删改不得导致外部的功能失效。前后端独自开发,并通过一套约定好的接口进行通信。

我遇到过的面试题

2020年05月07日 - 摹客

1. 数字转二进制(未回答上)

var a = 123;
console.log(a.toString(2))

2.智力题:两根蜡烛不同长度,但是都是一小时烧完,请确定15分钟的时长

当时解答:$\Delta t \times \Delta V = \Delta l$ ,假设我们能确定两根蜡烛长度a,b,那么速度差为$V_{a}=\dfrac{a}{60},V_{b}=\dfrac{b}{60},\Delta V=V_{a}-V_{b}=\dfrac{a-b}{60}, $

$\Delta l=\dfrac{a-b}{4} $ 只要烧了这么多就说明到了15分钟

网上的解法:

3.CSS题目:请为id为foo的div的第一个ul元素的偶数子元素设置红色

<div id="foo">
    <p>somethign</p>
    <ul>
        <li>itme1</li>
        <li>itme1</li>
        <li>itme1</li>
    </ul>
    <p>somethign</p>
    <ul>
        <li>itme1</li>
        <li>itme1</li>
        <li>itme1</li>
    </ul>
</div>
 #foo :nth-child(2) :nth-child(even){
    color: red;
  }

请格外注意细节!

参考资料

关于 js 中的回调函数 callback 作者:硕儿的编程之路
链接:https://juejin.im/post/58f71c720ce463006bcc464b
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

最后修改:2021 年 03 月 17 日
如果觉得我的文章对你有用,请随意赞赏