纪录一些前端经常运用的基本知识点
妙技树
BFC
BFC 定义: BFC(Block formatting context)直译为”块级格式化上下文”。它是一个自力的衬着地区,只要Block-level box介入, 它划定了内部的Block-level Box怎样规划,而且与这个地区外部毫不相干。
BFC规划划定规矩:
- 内部的Box会在垂直方向,一个接一个地安排。
- Box垂直方向的间隔由margin决议。属于同一个BFC的两个相邻Box的margin会发作堆叠
- 每一个元素的margin box的左侧, 与包括块border box的左侧相打仗(关于从左往右的格式化,不然相反)。纵然存在浮动也是云云。
- BFC的地区不会与float box堆叠。
- BFC就是页面上的一个断绝的自力容器,容器内里的子元素不会影响到外面的元素。反之也云云。
- 盘算BFC的高度时,浮动元素也介入盘算
哪些元素会天生BFC:
- 根元素
- float属性不为none
- position为absolute或fixed
- display为inline-block, table-cell, table-caption, flex, inline-flex
- overflow不为visible
浏览器衬着页面历程
- 用户输入URL地点
- 对URL地点举行DNS域名剖析
- 竖立TCP衔接(三次握手)
- 浏览器发送HTTP要求报文
- 服务器返回HTTP相应报文
- 封闭TCP衔接(四次挥手)
- 浏览器剖析文档资本并衬着页面
TCP
TCP三次握手
TCP四次挥手
JS单线程运行机制
- 音讯行列:音讯行列是一个先进先出的行列,它内里存放着种种音讯。
- 事宜轮回:事宜轮回是指主线程反复从音讯行列中取音讯、实行的历程。
主线程只会做一件事变,就是从音讯行列内里取音讯、实行音讯,再取音讯、再实行。当音讯行列为空时,就会守候直到音讯行列变成非空。而且主线程只要在将当前的音讯实行完成后,才会去取下一个音讯。这类机制就叫做事宜轮回机制,取一个音讯并实行的历程叫做一次轮回。音讯就是注册异步使命时增加的回调函数。
事宜轮回
macroTask(宏使命): 主代码块, setTimeout, setInterval, setImmediate, requestAnimationFrame, I/O, UI rendering
microTask(微使命): process.nextTick, Promise, Object.observe, MutationObserver
事宜
事宜流
- 事宜捕捉阶段
- 处于目的阶段
- 事宜冒泡阶段
事宜托付
不在事宜的发作地(直接dom)上设置监听函数,而是在其父元素上设置监听函数,经由过程事宜冒泡,父元素能够监听到子元素上事宜的触发,经由过程推断事宜发作元素DOM的范例,来做出差别的相应。
举例:最典范的就是ul和li标签的事宜监听
HTML
基本标签
<head></head>
<meta />
<link rel="stylesheet" href="" />
<title></title>
<body></body>
<center></center>
<section></section>
<article></article>
<aside></aside>
<div></div>
<ul></ul>
<li></li>
<p></p>
<h1></h1>
~
<h6></h6>
<button></button>
<input type="text" />
<a href=""></a>
<span></span>
<strong></strong>
<i></i>
CSS
CSS 款式
优先级: 行内款式 > 链接式 > 内嵌式 > @import 导入式
挑选器
/* 挑选一切元素 */
* {
}
/* 挑选 div 元素 */
div {
}
/* 挑选类名元素 */
.class {
}
/* 挑选 id 元素 */
#id {
}
/* 挑选 div 元素内的一切 p 元素 */
div p {
}
/* 挑选 div 元素内下一层级的 p 元素 */
div > p {
}
css挑选器权重: !important -> 行内款式 -> #id -> .class -> 元素和伪元素 -> * -> 继续 -> 默许
文本溢出
// 文本溢出单行显现
.single {
overflow: hidden;
text-overflow:ellipsis;
white-space: nowrap;
}
// 文本溢出多行显现
.multiple {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
overflow: hidden;
}
CSS3 新特征
- transition:过渡
- transform:扭转、缩放、挪动或许倾斜
- animation:动画
- gradient:渐变
- shadow:暗影
- border-radius:圆角
Javascript
原型与原型链
- 实例的 proto 属性(原型)即是其组织函数的 prototype 属性。
- Object.proto === Function.prototype
- Function.prototype.proto === Object.prototype
- Object.prototype.proto === null
继续完成
function extend(child, parent) {
var F = function() {}; // 空函数为中介,削减实例时占用的内存
F.prototype = parent.prototype; // f继续parent原型
child.prototype = new F(); // 实例化f,child继续,child、parent原型互不影响
child.prototype.constructor = child; // child组织函数指会自身,保证继续一致
child.super = parent.prototype; // 新增属性指向父类,保证子类继续完整
}
深拷贝
function deepCopy(s, t) {
t = t || (Object.prototype.toString.call(t) === "[object Array]" ? [] : {});
for (var i in s) {
if (typeof s[i] === "object") {
t[i] = deepCopy(s[i], t[i]);
} else {
t[i] = s[i];
}
}
return t;
}
Ajax
var ajax = {};
ajax.get = function(url, fn) {
var xhr = new XMLHttpRequest();
xhr.open("GET", url, true);
xhr.onreadystatechange = function() {
if (
xhr.readyState === 4 &&
(xhr.status === 200 || xhr.status === 403)
) {
fn.call(this, xhr.responseText);
}
};
xhr.send();
};
ajax.post = function(url, data, fn) {
var xhr = new XMLHttpRequest();
xhr.open("POST", url, true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.onreadystatechange = function() {
if (
xhr.readyState === 4 &&
(xhr.status === 200 || xhr.status === 403)
) {
fn.call(this, xhr.responseText);
}
};
xhr.send(data);
};
格式化日期
function formatDate(date, format) {
if (arguments.length === 0) return null;
format = format || "{y}-{m}-{d} {h}:{i}:{s}";
if (typeof date !== "object") {
if ((date + "").length === 10) date = parseInt(date) * 1000;
date = new Date(date);
}
const dateObj = {
y: date.getFullYear(),
m: date.getMonth() + 1,
d: date.getDate(),
h: date.getHours(),
i: date.getMinutes(),
s: date.getSeconds(),
a: date.getDay()
};
const dayArr = ["一", "二", "三", "四", "五", "六", "日"];
const str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (match, key) => {
let value = dateObj[key];
if (key === "a") return dayArr[value - 1];
if (value < 10) {
value = "0" + value;
}
return value || 0;
});
return str;
}
new 完成
function New(Class) {
let obj = {};
obj.__proto__ = Class.prototype;
let res = Class.call(obj);
return typeof res === 'object' ? res : obj;
}
call 完成
Function.prototype.callfb = function (ctx) {
if (typeof this !== 'function') {
throw new Error('Function undefined');
}
ctx = ctx || window;
const fn = ctx.fn;
ctx.fn = this;
const args = [...arguments].slice(1);
const res = ctx.fn(...args);
ctx.fn = fn;
return res;
}
apply 完成
Function.prototype.applyFb = function (ctx) {
if (typeof this !== 'function') {
throw new Error('Function undefined');
}
ctx = ctx || window;
const fn = ctx.fn;
ctx.fn = this;
const arg = arguments[1];
const res = Array.isArray(arg) ? ctx.fn(...arg) : ctx.fn();
ctx.fn = fn;
return res;
}
bind 完成
Function.prototype.bindFb = function (ctx) {
const fn = this;
const args = [...arguments].slice(1);
const F = function () {};
const fBind = function () {
return fn.apply(this instanceof fBind ? this : ctx, args.concat(...arguments))
}
if (fn.prototype) {
F.prototype = fn.prototype;
}
fBind.prototype = new F();
return fBind;
}
instanceof 完成
function instanceofFb(left, right) {
let proto, prototype = right.prototype;
proto = left.__proto__;
while (proto) {
if (proto === prototype) {
return true;
}
proto = proto.__proto__;
}
return false;
}
Promise 完成
function promiseFb(fn) {
const _this = this;
this.state = 'pending'; // 初始状况为pending
this.value = null;
this.resolvedCallbacks = []; // 这两个变量用于保留then中的回调,由于实行完Promise时状况能够照样pending
this.rejectedCallbacks = []; // 此时须要吧then中的回调保留起来轻易状况转变时挪用
function resolve(value) {
if (_this.state === 'pending') {
_this.state = 'resolved';
_this.value = value;
_this.resolvedCallbacks.map(cb => { cb(value) }); // 遍历数组,实行之前保留的then的回调函数
}
}
function reject(value) {
if (_this.state === 'pending') {
_this.state = 'rejected';
_this.value = value;
_this.rejectedCallbacks.map(cb => { cb(value) });
}
}
try {
fn(resolve, reject);
} catch (e) {
reject(e);
}
}
promiseFb.prototype.then = function (onFulfilled, onRejected) {
// 由于then的两个参数均为可选参数,
// 所以推断参数范例自身是不是为函数,假如不是,则须要给一个默许函数以下(轻易then不传参数时能够透传)
// 相似如许: Promise.resolve(4).then().then((value) => console.log(value))
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : fn => fn;
onRejected = typeof onRejected === 'function' ? onRejected : e => { throw e };
switch (this.state) {
case 'pending':
// 若实行then时仍为pending状况时,增加函数到对应的函数数组
this.resolvedCallbacks.push(onFulfilled);
this.rejectedCallbacks.push(onRejected);
break;
case 'resolved':
onFulfilled(this.value);
break;
case 'rejected':
onRejected(this.value);
break;
default: break;
}
}
debounce 防抖
function debounce(fn, wait, immediate) {
let timer;
return function () {
if (immediate) {
fn.apply(this, arguments);
}
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, arguments);
}, wait)
}
}
throttle 撙节
function throttle(fn, wait) {
let prev = new Date();
return function () {
const now = new Date();
if (now - prev > wait) {
fn.apply(this, arguments);
prev = now;
}
}
}
双向绑定
双向绑定:视图(View)的变化能及时让数据模型(Model)发作变化,而数据的变化也能及时更新到视图层.
Object.defineProperty
<!DOCTYPE html>
<html lang="en">
<head>
<title>mvvm</title>
</head>
<body>
<p>数据值:<span id="data"></span></p>
<p><input type="text" onkeyup="keyup()"></p>
<script>
var obj = {
data: ''
}
function keyup(e) {
e = e || window.event;
obj.data = e.target.value; // 更新数据值
}
Object.defineProperty(obj, 'data', {
get: function () {
return this.data;
},
set: function (newVal) {
document.getElementById('data').innerText = newVal; // 更新视图值
}
})
</script>
</body>
</html>
Proxy
<!DOCTYPE html>
<html lang="en">
<head>
<title>mvvm</title>
</head>
<body>
<p>数据值:<span id="data"></span></p>
<p><input type="text" onkeyup="keyup()"></p>
<script>
var obj = new Proxy({}, {
get: function (target, key, receiver) {
return Reflect.get(target, key, receiver);
},
set: function (target, key, value, receiver) {
if (key === 'data') {
document.getElementById('data').innerText = value; // 更新视图值
}
return Reflect.set(target, key, value, receiver);
}
})
function keyup(e) {
e = e || window.event;
obj.data = e.target.value; // 更新数据值
}
</script>
</body>
</html>
算法
冒泡排序
两两对照
function bubble(arr) {
const len = arr.length;
for (let i = 0; i < len; i++) {
for (let j = 0; j < len - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
let temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
return arr;
}
挑选排序
寻觅最小的数,将索引保留
function selection(arr) {
const len = arr.length;
let minIndex, temp;
for (let i = 0; i < len - 1; i++) {
minIndex = i;
for (let j = i + 1; j < len; j++) {
if (arr[j] < arr[minIndex]) {
minIndex = j;
}
}
temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
return arr;
}
Webpack
经常运用loader
- file-loader: 加载文件资本,如 字体 / 图片 等,具有挪动/复制/定名等功用;
- url-loader: 通经常运用于加载图片,能够将小图片直接转换为 Date Url,削减要求;
- babel-loader: 加载 js / jsx 文件, 将 ES6 / ES7 代码转换成 ES5,抹平兼容性问题;
- ts-loader: 加载 ts / tsx 文件,编译 TypeScript;
- style-loader: 将 css 代码以<style>标签的情势插进去到 html 中;
- css-loader: 剖析@import和url(),援用 css 文件与对应的资本;
- postcss-loader: 用于 css 的兼容性处置惩罚,具有浩瀚功用,比方 增加前缀,单元转换 等;
- less-loader / sass-loader: css预处置惩罚器,在 css 中新增了很多语法,提高了开辟效力;
经常运用plugin
- UglifyJsPlugin: 紧缩、殽杂代码;
- CommonsChunkPlugin: 代码支解;
- ProvidePlugin: 自动加载模块;
- html-webpack-plugin: 加载 html 文件,并引入 css / js 文件;
- extract-text-webpack-plugin / mini-css-extract-plugin: 抽离款式,天生 css 文件;
- DefinePlugin: 定义全局变量;
- optimize-css-assets-webpack-plugin: CSS 代码去重;
- webpack-bundle-analyzer: 代码剖析;
- compression-webpack-plugin: 运用 gzip 紧缩 js 和 css;
- happypack: 运用多历程,加快代码构建;
- EnvironmentPlugin: 定义环境变量;