BFC布局规则
内部的Box会在垂直方向,一个接一个地放置。
Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠。 => 用于清除上下margin重叠
每个元素的margin box的左边, 与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。 => 用于左右布局
BFC的区域不会与float box重叠。
BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
计算BFC的高度时,浮动元素也参与计算。 => 用于清除浮动
归纳形成BFC的几个要点
float的值不为none;
position的值为fixed或者absolute;
display的值为 table-cell, table-caption, inline-block, flex, 或者 inline-flex中的其中一个;
overflow的值不为visible。
先看一个简单的栗子:
假如我们有这样的文件结构:
app/
-lib/
-common.js
-model
-task.js
-test.js
在 task.js 里编写如下的代码:
var path = require(‘path’);
console.log(dirname);
console.log(filename);
console.log(process.cwd());
console.log(path.resolve(‘./‘));
在 model 目录下运行 node task.js 得到的输出是:
/Users/guo/Sites/learn/app/model.js
/Users/guo/Sites/learn/app/model.js/task.js
/Users/guo/Sites/learn/app/model.js
/Users/guo/Sites/learn/app/model.js
然后在 app 目录下运行 node model/task.js,得到的输出是:
/Users/guo/Sites/learn/app/model.js
/Users/guo/Sites/learn/app/model.js/task.js
/Users/guo/Sites/learn/app
/Users/guo/Sites/learn/app
那么,不好意思不是问题来了~T_T,我们可以得出一些肤浅的结论了:
dirname: 总是返回被执行的 js 所在文件夹的绝对路径
filename: 总是返回被执行的 js 的绝对路径
process.cwd(): 总是返回运行 node 命令时所在的文件夹的绝对路径
./: 跟 process.cwd() 一样、一样、一样的吗?
只有在 require() 时才使用相对路径(./, ../) 的写法,其他地方一律使用绝对路径,如下:
// 当前目录下
path.dirname(filename) + ‘/test.js’;
// 相邻目录下
path.resolve(dirname, ‘../lib/common.js’);
Pending
(进行中)、Resolved
(已完成,又称Fulfilled)和Rejected
(已失败)
如果调用resolve函数和reject函数时带有参数,那么它们的参数会被传递给回调函数。reject函数的参数通常是Error对象的实例,表示抛出的错误;resolve函数的参数除了正常的值以外,还可能是另一个Promise实例,表示异步操作的结果有可能是一个值,也有可能是另一个异步操作
1 2 3 4 5 6 7 8 9 10 11 12
| var p1 = new Promise(function (resolve, reject) { setTimeout(() => reject(new Error('fail')), 3000) }) var p2 = new Promise(function (resolve, reject) { setTimeout(() => resolve(p1), 1000) }) p2 .then(result => console.log(result)) .catch(error => console.log(error))
|
Promise.prototype.then()Promise.prototype.catch()
Promise实例具有then方法,也就是说,then方法是定义在原型对象Promise.prototype上的。它的作用是为Promise实例添加状态改变时的回调函数。前面说过,then方法的第一个参数是Resolved状态的回调函数,第二个参数(可选)是Rejected状态的回调函数。
then方法返回的是一个新的Promise实例(注意,不是原来那个Promise实例)。因此可以采用链式写法,即then方法后面再调用另一个then方法。
1 2 3 4 5 6
| p.then((val) => console.log("fulfilled:", val)) .catch((err) => console.log("rejected:", err)); p.then((val) => console.log("fulfilled:", val)) .then(null, (err) => console.log("rejected:", err));
|
Promise.all()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| Promise.prototype.all = function(promises) { let results = [] return new Promise((resolve, rejected) => { for(let i=0; i<promises.length; i++) { promises[i].then((res) => { results.push(res) if (i === promises.length -1) { resolve(results) } }).catch((err) => { reject(err) }) } }) }
|
Promise.race()
Promise.resolve()
有时需要将现有对象转为Promise对象,Promise.resolve方法就起到这个作用。
1 2 3
| Promise.resolve(42).then(function(value){ console.log(value); });
|
Promise.reject()
Promise.reject(reason)方法也会返回一个新的Promise实例,该实例的状态为rejected。它的参数用法与Promise.resolve方法完全一致。
手写Promise的polyfill
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| const PENDING = 'pending' const FULFILLED = 'fulfilled' const REJECTED = 'rejected' function MyPromise(executor) { this.state = PENDING; this.value = null; this.reason = null; this.onFulfilledCallbacks = []; this.onRejectedCallbacks = []; var self = this; function resolve(val) { if (self.state === PENDING) { self.state = FULFILLED; self.value = value; self.onFulfilledCallbacks.forEach(function(fulfilledCallback) { fulfilledCallback(); }); } } function rejected(reason) { if (self.state === PENDING) { self.state = REJECTED; self.reason = reason; self.onRejectedCallbacks.forEach(function(rejectedCallback) { rejectedCallback(); }); } } try { executor(resolve, rejected); } catch (reason) { reject(reason); } } MyPromise.prototype.then = function(onResolve, onRejected) { if (self.state === PENDING) { self.onFulfilledCallbacks.push(() => { onFuifilled(self.value); }); self.onRejectedCallbacks.push(() => { onRejected(self.reason); }); } if (this.state === FULFILLED) { onResolve(this.value) } if (this.state === REJECTED) { onRejected(this.reason) } }
|