内容简介:记录一些前端常用的基础知识点
记录一些前端常用的基础知识点
技能树
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: 定义环境变量;
以上所述就是小编给大家介绍的《前端知识汇总》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。