├── images ├── readme.md ├── eventloop.png ├── InterviewMap.png ├── T7$DI(QWJ)VK)QBTNCUZF34.png ├── 2c3151c5fe2669ff242614c04de86ef0_672x532.png ├── 67aa2ba68d8dac054c77a1b41e798c68_467x324.png ├── fa84428874feeb553665b291bac30b70_300x297.png └── e17edc7ae0617a002b2d77ef1d26ad4a_1057x372.png ├── JavaScript ├── 严格模式.md ├── event-loop.md ├── 原型与继承.md ├── 作用域、作用域链与闭包.md ├── 基础概念.md ├── this.md ├── 模块化规范.md ├── DOM-操作技术.md ├── 实用的几个 DOM 操作技巧.md ├── DOM-概念及API.md └── 数组、字符串、Map、Set方法整理.md ├── 服务器 ├── node.js │ ├── 操作数据库.md │ ├── 深入浅出node.js-part1.md │ ├── 深入浅出 node.js-part2(网络编程).md │ └── 深入浅出 node.js-part3.md ├── OS 基础知识.md ├── Nginx.md └── Linux 基础.md ├── CSS ├── 常见问题2.md ├── 常见问题1.md └── CSS Secrets-P1.md ├── Vue └── 书写规范.md ├── README.md ├── React └── 书写规范.md ├── Safety └── Safety.md ├── DataStruct ├── DataStruct.md └── Tree.md ├── Browser └── Browser.md └── 面试题 └── 面试题精选1.md /images/readme.md: -------------------------------------------------------------------------------- 1 | 存图片 2 | -------------------------------------------------------------------------------- /images/eventloop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChenMingK/Blog/HEAD/images/eventloop.png -------------------------------------------------------------------------------- /images/InterviewMap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChenMingK/Blog/HEAD/images/InterviewMap.png -------------------------------------------------------------------------------- /images/T7$DI(QWJ)VK)QBTNCUZF34.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChenMingK/Blog/HEAD/images/T7$DI(QWJ)VK)QBTNCUZF34.png -------------------------------------------------------------------------------- /images/2c3151c5fe2669ff242614c04de86ef0_672x532.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChenMingK/Blog/HEAD/images/2c3151c5fe2669ff242614c04de86ef0_672x532.png -------------------------------------------------------------------------------- /images/67aa2ba68d8dac054c77a1b41e798c68_467x324.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChenMingK/Blog/HEAD/images/67aa2ba68d8dac054c77a1b41e798c68_467x324.png -------------------------------------------------------------------------------- /images/fa84428874feeb553665b291bac30b70_300x297.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChenMingK/Blog/HEAD/images/fa84428874feeb553665b291bac30b70_300x297.png -------------------------------------------------------------------------------- /images/e17edc7ae0617a002b2d77ef1d26ad4a_1057x372.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChenMingK/Blog/HEAD/images/e17edc7ae0617a002b2d77ef1d26ad4a_1057x372.png -------------------------------------------------------------------------------- /JavaScript/严格模式.md: -------------------------------------------------------------------------------- 1 | 除了正常运行模式,ECMAscript 5 添加了第二种运行模式:”严格模式”(strict mode)。顾名思义,这种模式使得 Javascript 在更严格的条件下运行。 2 | 3 | 严格模式主要有以下限制: 4 | 5 | 1.变量必须声明后再使用 6 | 7 | 2.函数的参数不能有同名属性,否则报错 8 | 9 | 3.不能使用 with 语句 10 | 11 | 4.不能对只读属性赋值,否则报错 12 | 13 | 5.不能使用前缀 0 表示八进制数,否则报错 14 | 15 | 6.不能删除不可删除的属性,否则报错 16 | 17 | 7.不能删除变量 delete prop,会报错,只能删除属性 delete global[prop] 18 | 19 | 8.eval 不会在它的外层作用域引入变量 20 | 21 | 9.eval 和 arguments 不能被重新赋值 22 | 23 | 10.arguments 不会自动反映函数参数的变化 24 | 25 | 11.不能使用`arguments.callee` 26 | 27 | 12.不能使用`arguments.caller` 28 | 29 | 13.禁止 this 指向全局对象 30 | 31 | 14.不能使用 fn.caller 和 fn.arguments 获取函数调用的堆栈 32 | 33 | 15.增加了保留字(比如 protected、static 和 interface) 34 | 35 | ***** 36 | 37 | 设立”严格模式”的目的,主要有以下几个: 38 | 39 | 1.消除 Javascript 语法的一些不合理、不严谨之处,减少一些怪异行为; 40 | 41 | 2.消除代码运行的一些不安全之处,保证代码运行的安全; 42 | 43 | 3.提高编译器效率,增加运行速度; 44 | 45 | 4.为未来新版本的 Javascript 做好铺垫。 46 | 47 | 进入”严格模式”的标志,是下面这行语句:`"use strict"` 48 | -------------------------------------------------------------------------------- /服务器/node.js/操作数据库.md: -------------------------------------------------------------------------------- 1 | # mysql 操作 2 | ## 安装 mysql 模块 3 | - `cnpm install mysql` 4 | - `const mysql = require('mysql')` 5 | 6 | ## 建立数据库连接 7 | ```js 8 | // 连接数据库 9 | function connect() { 10 | return mysql.createConnection({ 11 | // 这里将常量统一维护在constant对象中 12 | host: constant.dbHost, // ip 13 | user: constant.dbUser, // mysql用户名 14 | password: constant.dbPwd, // mysql密码 15 | database: 'book' // 数据库名 16 | }) 17 | } 18 | const conn = connect() 19 | 20 | ``` 21 | 或者 22 | ```js 23 | const mysql = require('mysql') 24 | let connection = mysql.createConnection({ 25 | host: 'localhost', 26 | user: 'root', 27 | password: '123456', 28 | database: 'test' 29 | }) 30 | connection.connect() 31 | connection.query('SELECT 1 + 1 AS solution', function (error, results, fields) { 32 | if (error) throw error 33 | console.log(' The solution is: ', results[0].solution) 34 | }) 35 | ``` 36 | ## 增、删、查、改 37 | ### 查询数据 38 | step1:建立连接 39 | step2:创建 sql 语句字符串 40 | step3: 41 | ```js 42 | conn.query(sql, (err, results) => { 43 | if(err) { } 44 | else { } 45 | }) 46 | ``` 47 | ```js 48 | app.get('/book/detail', (req, res) => { 49 | const conn = connect() 50 | const fileName = req.query.fileName 51 | const sql = `select * from book where fileName='${fileName}'` 52 | conn.query(sql, (err, results) => { 53 | if (err) { 54 | res.json({ 55 | error_code: 1, 56 | msg: '电子书详情获取失败' 57 | }) 58 | } else { 59 | if (results && results.length === 0) { 60 | res.json({ 61 | error_code: 1, 62 | msg: '电子书详情获取失败' 63 | }) 64 | } else { 65 | const book = handleData(results[0]) 66 | res.json({ 67 | error_code: 0, 68 | msg: '获取成功', 69 | data: book 70 | }) 71 | } 72 | } 73 | conn.end() // 注意关闭数据库链接 74 | }) 75 | }) 76 | ``` 77 | results返回的数据格式是怎样的? 78 | ![](images/screenshot_1559784130377.png) 79 | 查询结果如下图 80 | ![](images/screenshot_1559784135680.png) 81 | 返回一个数组,results\[0\]可以直接获取到第一个对象的引用,results\[0\].Sno 可以直接获取到这个对象的 Sno 属性对应的值。 82 | 83 | ## 插入数据 84 | ```js 85 | // ...建立连接的过程省略 86 | const addSql = 'INSERT INTO websites(Id, name, url, alexa, country) VALUES(0, ?, ?, ?, ?)' 87 | const addSqlParams = ['菜鸟工具', 'https://c.runoob.com', '23453', 'CN'] 88 | connection.connect() 89 | connection.query(addSql, addSqlParams, function (err, result) { 90 | if (err) { 91 | console.log('[INSERT ERROR] - ', err.message) 92 | return 93 | } 94 | console.log('INSERT ID: ', result) 95 | }) 96 | connection.end() 97 | ``` 98 | 或者 99 | ```js 100 | const sql= 'INSERT INTO websites(Id, name, url, alexa, country) 101 | VALUES(0, '菜鸟工具', 'https://c.runoob.com', '23453', 'CN')' 102 | connection.query(sql, (err, result) => { 103 | // do something... 104 | }) 105 | ``` 106 | 一般都会使用模板字符串: 107 | ```js 108 | const query = req.query // 获取URL中的参数 109 | const sql = `SELECT * FROM ${query.table}` 110 | ``` 111 | 插入成功后返回的信息格式如下: 112 | ```js 113 | OKPacket { 114 | fieldCount: 0, 115 | affectedRows: 1, 116 | insertId: 3, 117 | serverStatus: 2, 118 | warningCount: 0, 119 | message: '', 120 | protocol41: true, 121 | changedRows: 0 } 122 | ``` 123 | 124 | ## 更新数据 125 | ```js 126 | // ...建立连接的过程省略 127 | const addSql = 'UPDATE websites SET name = ?, url = ? WHERE Id = ?' 128 | const addSqlParams = ['菜鸟移动站', 'https://m.runoob.com', 6] 129 | connection.connect() 130 | connection.query(addSql, addSqlParams, function (err, result) { 131 | if (err) { 132 | console.log('[UPDATE ERROR] - ', err.message) 133 | return 134 | } 135 | console.log('UPDATE affectedRows: ', result.affectedRows) 136 | }) 137 | connection.end() 138 | ``` 139 | 更新成功返回的信息格式如下:与 insert 操作一样 140 | ```js 141 | OKPacket { 142 | fieldCount: 0, 143 | affectedRows: 1, 144 | insertId: 3, 145 | serverStatus: 34, 146 | warningCount: 0, 147 | message: '(Rows matched: 1 Changed: 1 Warnings: 0)', 148 | protocol41: true, 149 | changedRows: 1 } 150 | ``` 151 | -------------------------------------------------------------------------------- /服务器/OS 基础知识.md: -------------------------------------------------------------------------------- 1 | # 操作系统的基本功能 2 | 1.进程管理 3 | 4 | 进程控制、进程同步、进程通信、死锁处理、处理机调度等。 5 | 6 | 2.内存管理 7 | 8 | 内存分配、地址映射、内存保护与共享、虚拟内存等。 9 | 10 | 3.文件管理 11 | 12 | 文件存储空间的管理、目录管理、文件读写管理和保护等。 13 | 14 | 4.设备管理 15 | 16 | 完成用户的 I/O 请求,方便用户使用各种设备,并提高设备的利用率。 17 | 18 | 主要包括缓冲管理、设备分配、设备处理、虛拟设备等。 19 | 20 | ## 系统调用 21 | 如果一个进程在用户态需要使用内核态的功能,就进行系统调用从而陷入内核,由操作系统代为完成。 22 | 23 | 24 | 25 | Linux 的系统调用主要有以下这些: 26 | 27 | | Task | Commands | 28 | | :-: | --- | 29 | | 进程控制 | fork(); exit(); wait(); | 30 | | 进程通信 | pipe(); shmget(); mmap(); | 31 | | 文件操作 | open(); read(); write(); | 32 | | 设备操作 | ioctl(); read(); write(); | 33 | | 信息维护 | getpid(); alarm(); sleep(); | 34 | | 安全 | chmod(); umask(); chown(); | 35 | # 进程与线程 36 | ## 进程 37 | 进程是资源分配的基本单位。 38 | 39 | 进程控制块 (Process Control Block, PCB) 描述进程的基本信息和运行状态,所谓的创建进程和撤销进程,都是指对 PCB 的操作。 40 | 41 | ## 线程 42 | 线程是独立调度的基本单位。 43 | 44 | 一个进程中可以有多个线程,它们共享进程资源。 45 | 46 | QQ 和浏览器是两个进程,浏览器进程里面有很多线程,例如 HTTP 请求线程、事件响应线程、渲染线程等等, 47 | 线程的并发执行使得在浏览器中点击一个新链接从而发起 HTTP 请求时,浏览器还可以响应用户的其它事件。 48 | 49 | 50 | 51 | ## 区别 52 | Ⅰ 拥有资源 53 | 54 | 进程是资源分配的基本单位,但是线程不拥有资源,线程可以访问隶属进程的资源。 55 | 56 | 更为具体地说,线程之间共享**堆**和**全局变量**,因为堆是在进程空间中开辟出来的,所以肯定是跨线程共享的; 57 | 58 | 同理,全局变量是整个程序所共享的,也应由线程共享。而每个线程都会独立地维护属于自己的**寄存器**与**栈**。 59 | 60 | Ⅱ 调度 61 | 62 | 线程是独立调度的基本单位,在同一进程中,线程的切换不会引起进程切换,从一个进程中的线程切换到另一个进程中的线程时,会引起进程切换。 63 | 64 | Ⅲ 系统开销 65 | 66 | 由于创建或撤销进程时,系统都要为之分配或回收资源,如内存空间、I/O 设备等,所付出的开销远大于创建或撤销线程时的开销。 67 | 68 | 类似地,在进行进程切换时,涉及当前执行进程 CPU 环境的保存及新调度进程 CPU 环境的设置,而线程切换时只需保存和设置少量寄存器内容,开销很小。 69 | 70 | Ⅳ 通信方面 71 | 72 | 线程间可以通过直接读写同一进程中的数据进行通信,但是进程通信需要借助 IPC。 73 | 74 | 具体来说,进程间通信一般有以下两种形式:1.共享内存 2.消息传递 75 | 76 | 77 | 78 | - 共享内存模式:建立一块供协作进程共享的内存区域,进程通过向此共享区域读或写入数据来交换信息。 79 | - 消息传递模式:通过在协作进程间交换消息来实现通信。 80 | 81 | # 程序在内存中的分布 82 | 83 | 84 | **代码段(.text)**:也称文本段(Text Segment),存放着程序的机器码和只读数据,可执行指令就是从这里取得的。如果可能,系统会安排好相同程序的多个运行实体共享这些实例代码。这个段在内存中一般被标记为只读,任何对该区的写操作都会导致段错误(Segmentation Fault)。 85 | 86 | **BSS段(.bss)**:BSS段(bss segment)通常是指用来存放程序中未初始化的全局变量和静态变量的一块内存区域。BSS 是英文 Block Started by Symbol 的简称。BSS 段属于静态内存分配。 87 | 88 | **数据段(.data)**:数据段(data segment)通常是指用来存放程序中已初始化的全局变量和静态变量的一块内存区域。数据段属于静态内存分配。 89 | 90 | **堆(Heap)**:用来存储程序运行时分配的变量。堆的大小并不固定,可动态扩张或缩减。堆的内存的分配与释放由应用程序控制,通常申请的内存都需要释放,如果没有释放,在程序运行结束后操作系统会自动回收。 91 | 92 | **栈(Stack)**:是一种用来存储函数调用时的临时信息的结构,如函数调用所传递的参数、函数的返回地址、函数的局部变量等。 在程序运行时由编译器在需要的时候分配,在不需要的时候自动清除。 93 | 94 | - 所谓**动态存储区域**: 即 堆  栈   95 | - 所谓**静态存储区域**:即 存储静态变量和全局变量以及代码段的部分 96 | 97 | # 死锁 98 | ## 必要条件 99 | 100 | 101 | - 互斥:每个资源要么已经分配给了一个进程,要么就是可用的。 102 | - 占有和等待:已经得到了某个资源的进程可以再请求新的资源。 103 | - 不可抢占:已经分配给一个进程的资源不能强制性地被抢占,它只能被占有它的进程显式地释放。 104 | - 环路等待:有两个或者两个以上的进程组成一条环路,该环路中的每个进程都在等待下一个进程所占有的资源。 105 | 106 | ## 死锁处理 107 | 主要有以下四种方法: 108 | - 鸵鸟策略 109 | - 死锁检测与死锁恢复 110 | - 死锁预防 111 | - 死锁避免 112 | 113 | ### 鸵鸟策略 114 | 把头埋在沙子里,假装根本没发生问题。 115 | 116 | 因为解决死锁问题的代价很高,因此鸵鸟策略这种不采取任务措施的方案会获得更高的性能。 117 | 118 | 当发生死锁时不会对用户造成多大影响,或发生死锁的概率很低,可以采用鸵鸟策略。 119 | 120 | 大多数操作系统,包括 Unix,Linux 和 Windows,处理死锁问题的办法仅仅是忽略它。 121 | ### 死锁检测与死锁恢复 122 | 不试图阻止死锁,而是当检测到死锁发生时,采取措施进行恢复。 123 | 124 | 125 | 126 | 上图为资源分配图,其中方框表示资源,圆圈表示进程。资源指向进程表示该资源已经分配给该进程,进程指向资源表示进程请求获取该资源。 127 | 128 | 图 a 可以抽取出环,如图 b,它满足了环路等待条件,因此会发生死锁。 129 | 130 | 每种类型一个资源的死锁检测算法是通过检测有向图是否存在环来实现,从一个节点出发进行深度优先搜索,对访问过的节点进行标记, 131 | 如果访问了已经标记的节点,就表示有向图存在环,也就是检测到死锁的发生。 132 | 133 | 134 | ### 死锁预防 135 | 在程序运行之前预防发生死锁。 136 | 137 | 1.破坏互斥条件 138 | 139 | 例如假脱机打印机技术允许若干个进程同时输出,唯一真正请求物理打印机的进程是打印机守护进程。 140 | 141 | 2.破坏占有和等待条件 142 | 143 | 一种实现方式是规定所有进程在开始执行前请求所需要的全部资源。 144 | 145 | 3.破坏不可抢占条件 146 | 147 | 4.破坏环路等待 148 | 149 | 给资源统一编号,进程只能按编号顺序来请求资源。 150 | 151 | ### 死锁避免 152 | 在程序运行时避免发生死锁。使用银行家算法来保证资源的合理分配:[https://blog.csdn.net/qq\_37205708/article/details/86550339](https://blog.csdn.net/qq_37205708/article/details/86550339) 153 | 154 | # 操作系统笔记十篇 155 | [https://blog.csdn.net/qq\_37205708/article/category/8618355](https://blog.csdn.net/qq_37205708/article/category/8618355) 156 | -------------------------------------------------------------------------------- /JavaScript/event-loop.md: -------------------------------------------------------------------------------- 1 | >这里只介绍浏览器中的事件循环,node 中的事件循环放在 node.js 专题部分 2 | 3 | ## 灵魂三问 4 | JavaScript 为什么是单线程的?JavaScript 为什么需要异步?JavaScript 单线程又是如何实现异步的? 5 | 6 | 7 | **1.JavaScript 为什么是单线程的?** 8 | 9 | 10 | 现在有 2 个线程 process1 process2,假设 JavaScript 是多线程的,所以他们可以对同一个 dom 同时进行操作。process1 删除了该 dom,而 process2 编辑了该 dom,同时下达 2 个矛盾的命令,浏览器究竟该如何执行呢?这样想,JavaScript 为什么被设计成单线程应该就容易理解了吧。 11 | 12 | 13 | **2.JavaScript 为什么需要异步?** 14 | 15 | 16 | 如果 JavaScript 中不存在异步,只能自上而下执行,如果上一行解析时间很长,那么下面的代码就会被阻塞。对于用户而言,阻塞就意味着"卡死",这样就导致了很差的用户体验,所以 JavaScript 中存在异步执行。 17 | 18 | 19 | **3.JavaScript 单线程又是如何实现异步的呢?** 20 | 21 | 22 | 是通过**事件循环**来实现的 23 | 24 | >为了利用多核 CPU 的计算能力,HTML5 提出 Web Worker 标准,允许 JavaScript 脚本创建多个线程,但是子线程完全受主线程控制,且不得操作 DOM。所以,这个新标准并没有改变 JavaScript 单线程的本质。 25 | 26 | 为什么说 JavaScript 是“非阻塞”的语言?非阻塞即:“程序不会因为某个任务而停下来” 27 | ```js 28 | console.log("程序时间:" + new Date().getTime()) 29 | 30 | setTimeout(function () { 31 | console.log("暂停一秒:" + new Date().getTime()) 32 | }, 1000) 33 | 34 | console.log('这是暂停一秒之后的时间:' + new Date().getTime()) 35 | ``` 36 | 简单来,如果上图的 setTimeout 换成 C++ 的 sleep(1000) 之类的,那么 C++ 是会确实地“睡眠”那么段时间的,而 JS 不会。如果我就是想实现这个功能呢?可以利用 Promise 实现: 37 | ```js 38 | async function test () { 39 | console.log('start') 40 | await sleep(3000) 41 | console.log('3s has passed') 42 | } 43 | 44 | function sleep (ms) { 45 | return new Promise((resolve, reject) => { 46 | setTimeout(() => { 47 | resolve() 48 | }, ms) 49 | }) 50 | } 51 | ``` 52 | ## 任务队列 53 | **任务队列(task queue)** 54 | 当遇到一个异步事件后,JavaScript 引擎并不会一直等待异步事件返回结果,而是会将这个事件挂在与执行栈不同的队列中,我们称之为任务队列。 55 | 这些任务又被细分为宏任务和微任务 56 | - 宏任务(macrotask):script(全局任务),setTimeout ,setInterval ,setImmediate **(node.js 独有)**,I/O(磁盘读写或网络通信) ,UI rendering(UI交互事件) 57 | - 微任务(microtask):process.nextTick **(node.js 独有)**, Promise.then, Object.observer(已废弃), MutationObserver. 58 | 59 | ## 事件循环(event loop) 60 | 这里首先要明确一点:浏览器是一个进程,其有多个线程(具体见 Broswer 章节) 61 | 一般情况下, 浏览器有如下五个线程: 62 | * GUI 渲染线程 63 | * JavaScript 引擎线程 64 | * 浏览器事件触发线程 65 | * 定时器触发线程 66 | * 异步 HTTP 请求线程 67 | 68 | 69 | GUI 渲染线程和 JavaScript 引擎线程是互斥的,其他线程相互之间都是可以并行执行的。 70 | 71 | 72 | 浏览器中,JavaScript 引擎循环地从任务队列中读取任务并执行,这种运行机制就叫做事件循环。 73 | 更准确地说,事件循环是按下面几个步骤执行的: 74 | 1. 执行同步代码,这属于宏任务(初始时的同步代码就是 script 整体代码) 75 | 2. 执行栈为空,查询是否有微任务 (microtask) 需要执行 76 | 3. 执行所有微任务 77 | 4. 必要的话渲染 UI 78 | 5. 然后开始下一轮 Event loop,执行宏任务中的异步代码 79 | 80 | 81 | 82 | ## 例题 83 | ```js 84 | setTimeout(function () { 85 | console.log(1); 86 | }, 0); 87 | 88 | Promise.resolve(function () { 89 | console.log(2); 90 | }) 91 | 92 | new Promise(function (resolve) { 93 | console.log(3); 94 | }); 95 | 96 | console.log(4); 97 | 98 | //上述代码的输出结果是什么??? 99 | ``` 100 | 正确答案是`------------------->` 3 4 1 101 | 解释如下: 102 | ``` js 103 | // 遇到 setTimeout 将 setTimeout 回调放入宏仁务队列中 104 | setTimeout(function () { 105 | console.log(1) 106 | }, 0) 107 | 108 | // 遇到了 promise,但是并没有 then 方法回调 109 | // 所以这句代码会在执行过程中进入我们当前的执行上下文 紧接着就出栈了 110 | Promise.resolve(function () { 111 | console.log(2) 112 | }) 113 | 114 | // 遇到了一个 new Promise,Promise 有一个原则就是在初始化 Promise 的时候Promise 内部的构造器函数会立即执行, 115 | // 因此在这里会立即输出一个 3,所以这个 3 是第一个输出的 116 | new Promise(function (resolve) { 117 | console.log(3) 118 | }) 119 | // 然后第二个输出 4 当代码执行完毕后回去微任务队列查找有没有任务, 120 | // 发现微任务队列是空的,那么就去宏仁务队列中查找,发现有一个我们刚刚放进去的setTimeout 回调函数, 121 | // 那么就取出这个任务进行执行,所以紧接着输出1 122 | console.log(4) 123 | ``` 124 | 125 | 太简单了?来看看这题: 126 | ```js 127 | console.log('begin'); // 1.begin 128 | setTimeout(() => { 129 | console.log('setTimeout 1'); // 3.setTimeout 1 130 | Promise.resolve() // Promise.resolve().then :直接把 then 回调放入微任务队列 131 | .then(() => { 132 | console.log('promise 1'); // 5.promise 1 133 | setTimeout(() => { 134 | console.log('setTimeout2'); // 8. setTimeout2 135 | }); 136 | }) 137 | .then(() => { 138 | console.log('promise 2'); // 7. promise 2 注意7比8要快,then 方法返回一个新的 Promise 对象 139 | }); 140 | new Promise(resolve => { 141 | console.log('a'); // 4. a 142 | resolve(); 143 | }).then(() => { 144 | console.log('b'); // 6. b 145 | }); 146 | }, 0); 147 | console.log('end'); // 2.end 148 | ``` 149 | -------------------------------------------------------------------------------- /CSS/常见问题2.md: -------------------------------------------------------------------------------- 1 | # 清除浮动 2 | 参考链接:[https://blog.csdn.net/h\_qingyi/article/details/81269667](https://blog.csdn.net/h_qingyi/article/details/81269667) 3 | 4 | 方案1:触发 BFC 实现清除浮动 5 | ```css 6 | .fahter{ 7 | width: 400px; 8 | overflow: hidden; 9 | } 10 | ``` 11 | 缺点:内容增多的时候容易造成不会自动换行导致内容被隐藏掉,无法显示要溢出的元素 12 | ***** 13 | 方案2:使用 after 伪元素清除浮动 14 | ```css 15 | .clearfix:after{/*伪元素是行内元素 正常浏览器清除浮动方法*/ 16 | content: ""; 17 | display: block; 18 | height: 0; 19 | clear:both; 20 | visibility: hidden; 21 | } 22 | .clearfix{ 23 | *zoom: 1;/*ie6清除浮动的方式 *号只有IE6-IE7执行,其他浏览器不执行*/ 24 | } 25 | ``` 26 | 优点:符合闭合浮动思想,结构语义化正确 27 | 缺点:ie6-7 不支持伪元素:after,使用 zoom:1 触发 hasLayout. 28 | ***** 29 | 方案3:使用 before 和 after 双伪元素清除浮动 30 | ```css 31 | .clearfix:after,.clearfix:before{ 32 | content: ""; 33 | display: table; /* ??? */ 34 | } 35 | .clearfix:after{ 36 | clear: both; 37 | } 38 | .clearfix{ 39 | *zoom: 1; 40 | } 41 | ``` 42 | 43 | # 两侧宽度固定、中间宽度自适应的三栏布局 44 | 参考链接 45 | 46 | [https://blog.csdn.net/Cinderella\_hou/article/details/52156333](https://blog.csdn.net/Cinderella_hou/article/details/52156333) 47 | 48 | [https://chokcoco.github.io/CSS-Inspiration/#/./layout/holy-grail-layout](https://chokcoco.github.io/CSS-Inspiration/#/./layout/holy-grail-layout) 49 | 50 | [https://www.cnblogs.com/hfdj/p/7554933.html](https://www.cnblogs.com/hfdj/p/7554933.html) 51 | 52 | [https://www.jianshu.com/p/81ef7e7094e8](https://www.jianshu.com/p/81ef7e7094e8) 53 | 54 | 解决方案:绝对定位、圣杯布局及双飞翼布局方案、 flex 方案 55 | 56 | ## 圣杯布局 57 | 原理: 58 | * 圣杯布局的关键点是通过 margin-left 与 left 属性将左右两列放置到准确的位置 59 | * 圣杯布局的关键点父元素需要设置 padding 60 | * 圣杯布局的关键点 margin-left 取值为百分比时,是以其父元素的宽度为基准的 61 | 62 | 缩放浏览器能看到自适应效果,分析过程见链接1 63 | 64 | ```html 65 | 66 | 67 | 68 | 69 | 三栏自自适应布局 70 | 71 | 111 | 112 | 113 |
114 |
115 |
116 | 117 |
118 | 119 | 120 | 121 | ``` 122 | 123 | ## 双飞翼布局 124 | 双飞翼布局左中右三列布局,渲染顺序中间列书写在前保证提前渲染,左右两列定宽,中间列自适应剩余宽度。 125 | 126 | 双飞翼布局与圣杯布局的不同之处,圣杯布局的的左中右三列容器,中间middle多了一个子容器存在,**通过控制 middle 的子容器的 margin 或者 padding 空出左右两列的宽度**。 127 | 128 | * 双飞翼布局的关键点是通过 margin-left 属性将左右两列放置到准确的位置,通过控制 middle 的子容器的 margin 或者 padding 空出左右两列的宽度 129 | * 双飞翼布局的关键点父元素不需要设置 padding 130 | * 双飞翼布局的关键点 margin-left 取值为百分比时,是以其父元素的宽度为基准的 131 | 132 | ```html 133 | 134 | 135 | 136 | 137 | 三栏自自适应布局 138 | 139 | 178 | 179 | 180 |
181 |
182 |
183 |
184 | 185 | 186 | 187 | 188 | ``` 189 | > 我感觉 float 布局就是玄学吧....... 190 | 191 | 192 | ## 使用 flex 193 | ```html 194 | 195 |
196 |
197 |
198 | 199 |
200 | ``` 201 | ```css 202 | #container { 203 | display: flex; 204 | } 205 | 206 | #center { 207 | flex: 1; // 1 1 auto 208 | } 209 | 210 | #left { 211 | flex: 0 0 200px; 212 | order: -1; 213 | } 214 | 215 | #right { 216 | flex: 0 0 150px; 217 | } 218 | ``` 219 | 220 | -------------------------------------------------------------------------------- /Vue/书写规范.md: -------------------------------------------------------------------------------- 1 | 节选自:[Vue 风格指南](https://cn.vuejs.org/v2/style-guide/) 2 | 3 | ## 1.组件名为多个单词,根组件 App 和内置组件 \ \ 等除外 4 | ```js 5 | // bad 6 | Vue.component('todo', { 7 | // ... 8 | }) 9 | export default { 10 | name: 'Todo', 11 | // ... 12 | } 13 | // good 14 | Vue.component('todo-item', { 15 | // ... 16 | }) 17 | export default { 18 | name: 'TodoItem', 19 | // ... 20 | } 21 | ``` 22 | ## 2.组件的 data 必须是一个函数 23 | 当在组件中使用`data`属性的时候 (除了`new Vue`外的任何地方),它的值必须是返回一个对象的函数。当`data`的值是一个对象时,它会在这个组件的所有实例之间共享,如果该组件被复用将难以管理数据。 24 | ```js 25 | // good 26 | export default { 27 | data () { 28 | return { 29 | foo: 'bar' 30 | } 31 | } 32 | } 33 | ``` 34 | ## 3.Prop 定义应该尽量详细,至少需要指定其类型 35 | 细致的 prop 定义有两个好处: 36 | - 它们写明了组件的 API,所以很容易看懂组件的用法; 37 | - 在开发环境下,如果向一个组件提供格式不正确的 prop,Vue 将会告警,以帮助你捕获潜在的错误来源。 38 | ```js 39 | // good 40 | props: { 41 | status: String 42 | } 43 | 44 | // better 45 | props: { 46 | status: { 47 | type: String, 48 | required: true, 49 | validator: function (value) { 50 | return [ 51 | 'syncing', 52 | 'synced', 53 | 'version-conflict', 54 | 'error' 55 | ].indexOf(value) !== -1 56 | } 57 | } 58 | } 59 | ``` 60 | ## 4.避免 v-if 和 v-for 同时用在一个元素上 61 | 当 Vue 处理指令时,`v-for`比`v-if`具有更高的优先级,所以这个模板: 62 | ```html 63 | 72 | ``` 73 | 将会经过如下运算: 74 | ```js 75 | this.users.map(function (user) { 76 | if (user.isActive) { 77 | return user.name 78 | } 79 | }) 80 | ``` 81 | 因此哪怕我们只渲染出一小部分用户的元素,也得在每次重渲染的时候遍历整个列表,不论活跃用户是否发生了变化。 82 | 83 | 通过将其更换为在如下的一个计算属性上遍历: 84 | ```js 85 | computed: { 86 | activeUsers: function () { 87 | return this.users.filter(function (user) { 88 | return user.isActive 89 | }) 90 | } 91 | } 92 | ``` 93 | ```html 94 | 102 | ``` 103 | 我们将会获得如下好处: 104 | - 过滤后的列表只会在 users 数组发生相关变化时才被重新运算,过滤更高效。 105 | - 使用 v-for="user in activeUsers" 之后,我们在渲染的时候只遍历活跃用户,渲染更高效。 106 | - 解耦渲染层的逻辑,可维护性 (对逻辑的更改和扩展) 更强。 107 | 108 | ## 5.为组件样式设置作用域 109 | 当 \ 116 | 117 | 120 | ``` 121 | 122 | 转换结果: 123 | ```html 124 | 129 | 130 | 133 | ``` 134 | ## 6.组件文件 135 | 只要有能够拼接文件的构建系统,就把每个组件单独分成文件。 136 | ```js 137 | // bad 138 | Vue.component('TodoList', { 139 | // ... 140 | }) 141 | 142 | 143 | // good 144 | components/ 145 | |- TodoList.js 146 | |- TodoItem.js 147 | ``` 148 | ## 7.组件文件的大小写 149 | 单文件组件的文件名应该要么始终是单词大写开头 (PascalCase),要么始终是横线连接 (kebab-case)。 150 | ```js 151 | // bad 152 | components/ 153 | |- mycomponent.vue 154 | components/ 155 | |- myComponent.vue 156 | 157 | // good 158 | components/ 159 | |- MyComponent.vue 160 | components/ 161 | |- my-component.vue 162 | ``` 163 | ## 8.基础组件名 164 | 应用特定样式和约定的基础组件 (也就是展示类的、无逻辑的或无状态的组件) 应该全部以一个特定的前缀开头,比如 Base、App 或 V。 165 | ```js 166 | // bad 167 | components/ 168 | |- MyButton.vue 169 | |- VueTable.vue 170 | |- Icon.vue 171 | 172 | // good 173 | components/ 174 | |- BaseButton.vue 175 | |- BaseTable.vue 176 | |- BaseIcon.vue 177 | components/ 178 | |- AppButton.vue 179 | |- AppTable.vue 180 | |- AppIcon.vue 181 | components/ 182 | |- VButton.vue 183 | |- VTable.vue 184 | |- VIcon.vue 185 | ``` 186 | ## 9.单例组件名 187 | **只应该拥有单个活跃实例的组件应该以`The`前缀命名,以示其唯一性。** 188 | 这不意味着组件只可用于一个单页面,而是*每个页面* 只使用一次。这些组件永远不接受任何 prop,因为它们是为你的应用定制的,而不是它们在你的应用中的上下文。如果你发现有必要添加 prop,那就表明这实际上是一个可复用的组件,*只是目前*在每个页面里只使用一次。 189 | ```js 190 | // bad 191 | components/ 192 | |- Heading.vue 193 | |- MySidebar.vue 194 | // good 195 | components/ 196 | |- TheHeading.vue 197 | |- TheSidebar.vue 198 | ``` 199 | ## 10.模板中的组件名大小写 200 | **对于绝大多数项目来说,在单文件组件和字符串模板中组件名应该总是 PascalCase 的——但是在 DOM 模板中总是 kebab-case 的。** 201 | 由于 HTML 是大小写不敏感的,在 DOM 模板中必须仍使用 kebab-case。 202 | ```html 203 | // bad 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | // good 212 | 213 | 214 | 215 | 216 | ``` 217 | ## 11.多个特性的元素 218 | **多个特性的元素应该分多行撰写,每个特性一行。** 219 | ```html 220 | // bad 221 | Vue Logo 222 | 223 | 224 | 225 | // good 226 | Vue Logo 230 | 231 | 236 | ``` 237 | ## 12.带引号的特性值 238 | **非空 HTML 特性值应该始终带引号 (一般是双引号)** 239 | 在 HTML 中不带空格的特性值是可以没有引号的,但这鼓励了大家在特征值里 *不写* 空格,导致可读性变差。 240 | ```html 241 | // bad 242 | 243 | 244 | // good 245 | 246 | 247 | ``` 248 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 知识点 2 | 3 | 4 | ## :books: WebKnowledges-Notes 5 | 学习笔记、开发技巧、面试题、前后端知识整理 6 | 7 | 如果你觉得对你有帮助,点个 star 对我来说就是最大的鼓励啦~ 8 | 9 | 10 |
11 | JavaScript 基础 12 | 13 | - [基础概念](https://github.com/ChenMingK/Blog/blob/master/JavaScript/%E5%9F%BA%E7%A1%80%E6%A6%82%E5%BF%B5.md) 14 | - [作用域、作用域链、闭包](https://github.com/ChenMingK/Blog/blob/master/JavaScript/%E4%BD%9C%E7%94%A8%E5%9F%9F%E3%80%81%E4%BD%9C%E7%94%A8%E5%9F%9F%E9%93%BE%E4%B8%8E%E9%97%AD%E5%8C%85.md) 15 | - [this](https://github.com/ChenMingK/Blog/blob/master/JavaScript/this.md) 16 | - [原型与继承](https://github.com/ChenMingK/Blog/blob/master/JavaScript/%E5%8E%9F%E5%9E%8B%E4%B8%8E%E7%BB%A7%E6%89%BF.md) 17 | - [数组、字符串、Map、Set方法整理](https://github.com/ChenMingK/Blog/blob/master/JavaScript/%E6%95%B0%E7%BB%84%E3%80%81%E5%AD%97%E7%AC%A6%E4%B8%B2%E3%80%81Map%E3%80%81Set%E6%96%B9%E6%B3%95%E6%95%B4%E7%90%86.md) 18 | - [事件循环](https://github.com/ChenMingK/Blog/blob/master/JavaScript/event-loop.md) 19 | - [DOM](https://github.com/ChenMingK/Blog/blob/master/JavaScript/DOM-%E6%A6%82%E5%BF%B5%E5%8F%8AAPI.md) 20 | - [常见 Coding](https://github.com/ChenMingK/WebKnowledges-Notes/blob/master/JS-Coding/JS-Coding.md) 21 | - [正则表达式](https://github.com/ChenMingK/Blog/blob/master/JavaScript/%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F.md) 22 | - [ES6](https://github.com/ChenMingK/Blog/blob/master/JavaScript/ES6%20%E7%9F%A5%E8%AF%86%E7%82%B9%E6%A2%B3%E7%90%86.md) 23 | - [设计模式](https://github.com/ChenMingK/Blog/blob/master/JavaScript/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F.md) 24 | - [AJAX](https://github.com/ChenMingK/Blog/blob/master/JavaScript/AJAX.md) 25 | - [事件](https://www.kancloud.cn/chenmk/web-knowledges/1163864) 26 |
27 | 28 |
29 | CSS 30 | 31 | - [CSS Secrets P1](https://github.com/ChenMingK/WebKnowledges-Notes/blob/master/CSS/CSS%20Secrets-P1.md) 32 | - [常见问题](https://github.com/ChenMingK/WebKnowledges-Notes/blob/master/CSS/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%981.md) 33 | - [移动端适配](https://www.kancloud.cn/chenmk/web-knowledges/1201809) 34 | - [SVG](https://www.kancloud.cn/chenmk/web-knowledges/1179909) 35 |
36 | 37 |
38 | Vue 39 | 40 | - [Vue 知识整理](https://www.kancloud.cn/chenmk/web-knowledges/1176000) 41 | - [Vue 书写规范](https://github.com/ChenMingK/Blog/blob/master/Vue/%E4%B9%A6%E5%86%99%E8%A7%84%E8%8C%83.md) 42 | - [vue-router & vuex 的使用](https://www.kancloud.cn/chenmk/web-knowledges/1185871) 43 | - [深入浅出 Vue](https://www.kancloud.cn/chenmk/web-knowledges/1187397) 44 |
45 | 46 |
47 | React 48 | 49 | - [React 基础知识](https://www.kancloud.cn/chenmk/web-knowledges/1144248) 50 | - [React 书写规范](https://www.kancloud.cn/chenmk/web-knowledges/1144249) 51 | - [redux & react-router 的使用](https://www.kancloud.cn/chenmk/web-knowledges/1144250) 52 | - [深入浅出 React 与 Redux 笔记](https://www.kancloud.cn/chenmk/web-knowledges/1164851) 53 |
54 | 55 | 56 |
57 | Others 58 | 59 | - [Browser](https://github.com/ChenMingK/WebKnowledges-Notes/blob/master/Browser/Browser.md) 60 | - [Performance](https://www.kancloud.cn/chenmk/web-knowledges/1078353) 61 | - [Safety](https://www.kancloud.cn/chenmk/web-knowledges/1078354) 62 | - [Network](https://www.kancloud.cn/chenmk/web-knowledges/1078352) 63 | - [DataStruct](https://www.kancloud.cn/chenmk/web-knowledges/1254425) 64 | - [Algorithm](https://www.kancloud.cn/chenmk/web-knowledges/1254424) 65 |
66 | 67 | 68 |
69 | 服务器 70 | 71 | - [OS 基础知识](https://github.com/ChenMingK/WebKnowledges-Notes/blob/master/%E6%9C%8D%E5%8A%A1%E5%99%A8/OS%20%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86.md) 72 | - [Linux 基础](https://github.com/ChenMingK/WebKnowledges-Notes/blob/master/%E6%9C%8D%E5%8A%A1%E5%99%A8/Linux%20%E5%9F%BA%E7%A1%80.md) 73 | - [Nginx 常用配置](https://github.com/ChenMingK/WebKnowledges-Notes/blob/master/%E6%9C%8D%E5%8A%A1%E5%99%A8/Nginx.md) 74 | - [深入浅出 node.js](https://github.com/ChenMingK/WebKnowledges-Notes/blob/master/%E6%9C%8D%E5%8A%A1%E5%99%A8/node.js/%E6%B7%B1%E5%85%A5%E6%B5%85%E5%87%BAnode.js-part1.md) 75 |
76 | 77 |
78 | Canvas & WebGL 79 | 80 | - [Canvas 学习笔记 - 持续更新中...](https://www.kancloud.cn/chenmk/web-knowledges/1380581) 81 |
82 | 83 | ## :coffee: 阅读 84 | [线上版本阅读更清晰](https://www.kancloud.cn/chenmk/web-knowledges/content) 85 | 86 | ## :ice_cream: 资源推荐 87 | - [奇舞周刊](https://weekly.75team.com/) 88 | - [饿了么前端](https://zhuanlan.zhihu.com/ElemeFE) 89 | - [掘金小册](https://github.com/InterviewMap/CS-Interview-Knowledge-Map) 90 | - [后端面试宝典](https://github.com/CyC2018/CS-Notes) 91 | - [冴羽的博客](https://github.com/mqyqingfeng/Blog) 92 | - [国服第一切图仔](https://www.cnblogs.com/coco1s/) 93 | - [张鑫旭的博客](https://www.zhangxinxu.com/wordpress/) 94 | - [阮一峰的网络日志](http://www.ruanyifeng.com/blog/) 95 | - [小火柴的蓝色理想](https://www.cnblogs.com/xiaohuochai/) 96 | - [技术胖](https://juejin.im/user/5875dfc7a22b9d0058a96d06) 97 | 98 | ## :hammer: 工具 99 | - [BootCDN](https://www.bootcdn.cn/):稳定、快速、免费的前端开源项目 CDN 加速服务 100 | - [颜色对照表](http://tool.chinaz.com/tools/use):网页颜色搭配表及颜色搭配技巧 101 | - [字体图标库](https://www.iconfont.cn/home/index?spm=a313x.7781069.1998910419.2):iconfont 102 | - [IconMoon](https://icomoon.io/app/#/select):svg 转 css @font-face 导入 103 | - [github 图标](https://github.com/caiyongji/emoji-list):github 图标大全 104 | - [canvas API](https://www.canvasapi.cn/):canvas API 中文文档 105 | - [ALIBABA FUTION DESIGN](https://fusion.design/design/component/balloon):设计指南 106 | - [draw.io](https://www.draw.io/):绘图 107 | - [https://www.geogebra.org/](https://www.geogebra.org/):数学在线绘图工具 108 | 109 | ## :sparkles: demos 110 | - [vue 开发一个简易的员工管理界面](https://github.com/ChenMingK/staffSystem) 111 | - [vue epub 电子书书城](https://github.com/ChenMingK/epub-Proj) 112 | - [vue socket.io 简易聊天室](https://github.com/ChenMingK/chat-room) 113 | - [react 新手上路-仿简书网](https://github.com/ChenMingK/blog-proj) 114 | -------------------------------------------------------------------------------- /服务器/Nginx.md: -------------------------------------------------------------------------------- 1 | # 正向代理与反向代理 2 | **正向代理**:用户想从服务器拿资源数据,但是只能通过 proxy 服务器才能拿到, 3 | 所以用户 A 只能去访问 proxy 服务器然后通过 proxy 服务器去服务器 B 拿数据, 4 | 这种情况用户是明确知道你要访问的是谁,在我们生活中最典型的案例就是“翻墙“了,也是通过访问代理服务器最后访问外网的。 5 | 6 | **反向代理**:客户端访问服务器时,并不知道会访问哪一台,感觉就是客户端访问了 Proxy 一样, 7 | 而实则就是当 Proxy 关口拿到用户请求的时候会转发到代理服务器中的随机(算法)某一台。 8 | 而在用户看来,他只是访问了 Proxy 服务器而已,典型的例子就是负载均衡。 9 | 10 |    11 | 12 | # 配置文件结构 13 | ```shell 14 | ... #全局块 15 | 16 | events { #events块 17 | ... 18 | } 19 | 20 | http #http块 21 | { 22 | ... #http全局块 23 | server #server块 24 | { 25 | ... #server全局块 26 | location [PATTERN] #location块 27 | { 28 | ... 29 | } 30 | location [PATTERN] 31 | { 32 | ... 33 | } 34 | } 35 | server 36 | { 37 | ... 38 | } 39 | ... #http全局块 40 | } 41 | ``` 42 | 1.全局块 43 | 44 | 配置影响 nginx 全局的指令。一般有运行 nginx 服务器的用户组,nginx 进程 pid 存放路径, 45 | 日志存放路径,配置文件引入,允许生成 worker process 数等。 46 | 47 | 2.events 块 48 | 49 | 配置影响 nginx 服务器或与用户的网络连接。有每个进程的最大连接数, 50 | 选取哪种事件驱动模型处理连接请求,是否允许同时接受多个网路连接,开启多个网络连接序列化等。 51 | 52 | 3.http 块 53 | 54 | 可以嵌套多个 server,配置代理,缓存,日志定义等绝大多数功能和第三方模块的配置。 55 | 如文件引入,mime-type 定义,日志自定义,是否使用 sendfile 传输文件,连接超时时间,单连接请求数等。 56 | 57 | 4.server 块 58 | 59 | 配置虚拟主机的相关参数,一个 http 块中可以有多个 server。 60 | 61 | 5.location 块 62 | 63 | 配置请求的路由,以及各种页面的处理情况。 64 | 65 | # 常用功能及其配置 66 | ## 做静态资源服务器 67 | 将静态资源(如jpg | png | css | js等)放在如下配置的`f:/nginx-1.12.2/static`目录下 68 | 69 | 然后在 nginx 配置文件中做如下配置(注意:静态资源配置只能放在 location / 中),浏览器中访问  `http://localhost:80/1.png` 70 | 71 | 即可访问到 `f:/nginx-1.12.2/static` 目录下的 1.png 图片 72 | 73 | 74 | 75 | 即访问 80 端口就相当于找到 root 这个目录。 76 | 77 | location 修饰符:[https://www.cnblogs.com/xiaoliangup/p/9175932.html](https://www.cnblogs.com/xiaoliangup/p/9175932.html) 78 | 79 | ## 负载均衡 80 | >负载均衡(Load Balance)其意思就是分摊到多个操作单元上进行执行,例如 Web 服务器、FTP服务器、企业关键应用服务器和其它关键任务服务器等,从而共同完成工作任务。 81 | 82 | 83 | 84 | 85 | 服务器 `localhost:8080 `挂掉时,nginx 能将请求自动转向服务器 `192.168.101.9:8080` 86 | 87 | 上面还加了一个 weight 属性,此属性表示各服务器被访问到的权重,weight 越高被访问到的几率越高。 88 | 89 | ## CORS跨域配置 90 | 91 | 92 | 93 | 上面与跨域先关的其实只有 `add_header Access-Control-Allow-Origin *` 这一行,这里再介绍下其他设置 94 | 95 | 注意文件目录是 / 而不是 \\ 96 | - autoindex on 表示列出文件目录(访问时可以看到一个文件列表) 97 | - location / 表示对所有经过的请求的操作 98 | 这里添加一个 `header Access-Control-Allow-Origin \* ` 指定允许哪个域的请求,* 表示任意 99 | - Cache-Control 一行表示每次访问时不做缓存,如果文件经常变动,缓存可能导致文件未及时更新 100 | - `no-cache` 表示每次使用静态资源时都需要向服务端请求(进行过期认证),通常情况下,过期认证需要配合 etag 和 Last-Modified 进行一个比较 101 | - `must-revalidate` 作用与 no-caceh 相同,但更严格,强制意思更明显(理论上) 102 | 103 | 与跨域相关的头部信息如下: 104 | 105 | Access-Control-Allow-Origin: 指定允许哪些源的网页发送请求. 106 | 107 | Access-Control-Allow-Credentials: 指定是否允许 cookie 发送. 108 | 109 | Access-Control-Allow-Methods: 指定允许哪些请求方法. 110 | 111 | Access-Control-Allow-Headers: 指定允许哪些常规的头域字段, 比如说 Content-Type. 112 | 113 | Access-Control-Expose-Headers: 指定允许哪些额外的头域字段, 比如说 X-Custom-Header. 114 | 115 | ## 开启 gzip 压缩 116 | 使用 gzip 压缩可以大大减小文件的体积,Nginx 配置如下: 117 | ```shell 118 | server { 119 | gzip on; 120 | gzip_types text/plain application/javascript application/x-javascript 121 | text/javascript text/xml text/css; 122 | } 123 | ``` 124 | 125 | ## 设定缓存时间(一般对静态资源才做设置) 126 | ```shell 127 | location ~* \.(jpg|jpeg|png|gif|webp)$ { 128 | expires 30d; 129 | } 130 | location ~* \.(css|js)$ { 131 | expires 7d; 132 | } 133 | ``` 134 | 如果要强制不缓存,可以把 expires 时间设置为 0 。 135 | 另外,开启 etag 只需要一行 136 | ```shell 137 | etag on; 138 | ``` 139 | 由于 etag 要使用少数的字符表示一个不定大小的文件(如 Etag: "58c4e2a1-f7"),所以 etag 是有重合的风险的,如果网站的信息特别重要,连很小的概率如百万分之一都不允许,那么就不要使用 etag 了。使用 etag 的代价是增加了服务器的计算负担,特别是当文件比较大时。 140 | 141 | ## 使用 HTTP 2.0 142 | HTTP/2 需要使用 nginx 1.10.0 和 openssl 1.0.2 以上版本,nginx.conf 配置如下: 143 | ```shell 144 | listen 443 ssl http2; 145 | ``` 146 | 对于不支持 HTTP/2 的浏览器,nginx 会自动处理,因为 HTTP/2 的实现基本只支持 HTTPS,HTTPS 连接过程中需要先握手,浏览器会发送一个 Client Hello 的包给服务,这个包里面会有它是否支持 h2 的信息。如果没有这些信息,nginx 会自动切换到 HTTP/1.1,所以能够兼容老的浏览器和客户端。 147 | 148 | ## 一个 node.js 例子 149 | 一个十分常见的需求:处理请求,如果是静态文件,Nginx 直接返回,否则交给 Node 服务器处理。首先创建了一个 Node 服务器: 150 | ``` js 151 | const http = require('http'); 152 | http.createServer((req, res) => { 153 | res.end('hello world'); 154 | }).listen(9000); 155 | ``` 156 | 任何请求过来都返回 `hello world`,简版的 Nginx 配置如下, 157 | ```server 158 | events { 159 | # 这里可不写东西 160 | use epoll; 161 | } 162 | http { 163 | server { 164 | listen 127.0.0.1:8888; 165 | # 如果请求路径跟文件路径按照如下方式匹配找到了,直接返回 166 | try_files $uri $uri/index.html; 167 | location ~* ^/(js|css|image|font)/$ { 168 | # 静态资源都在 static 文件夹下 169 | root /home/barret/www/static/; 170 | } 171 | location /app { 172 | # Node.js 在 9000 开了一个监听端口 173 | proxy_pass http://127.0.0.1:9000; 174 | } 175 | # 上面处理出错或者未找到的,返回对应状态码文件 176 | error_page 404 /404.html; 177 | error_page 502 503 504 /50x.html; 178 | } 179 | } 180 | ``` 181 | 首先 try_files,尝试直接匹配文件;没找到就匹配静态资源;还没找到就交给 Node 处理;否则就返回 4xx/5xx 的状态码。 182 | 183 | try_files 指令可以用在 server 部分,不过最常见的还是用在 location 部分,它会按照给定的参数顺序进行尝试,第一个被匹配到的将会被使用。$uri 是内置预定义变量,表示当前请求的标准化 URI。 184 | 185 | # 常用命令 186 | 1.检查 80 端口是否被占用的命令: 187 | ```shell 188 | netstat -ano | findstr 0.0.0.0:80` 或 `netstat -ano | findstr "80" 189 | ``` 190 | 2.修改 nginx 的配置文件后重新加载 191 | ```shell 192 | nginx -s reload 193 | ``` 194 | 3.关闭 nginx 195 | ```shell 196 | nginx -s stop # 快速停止 nginx   197 | nginx -s quit # 完整有序地停止 nginx 198 | 199 | taskkill /f /t /im nginx.exe # windows? 200 | ``` 201 | 4.列出所有 nginx 进程 202 | ```shell 203 | ps -aux | grep nginx # Linux 204 | 205 | tasklist /fi "imagename eq nginx.exe" # windows 206 | ``` 207 | 5.查找 nginx 配置文件的位置 208 | 209 | 先找出 nginx 可执行文件的路径`ps -ef | grep nginx` 210 | 211 | 212 | 213 | 这个`/usr/local/nginx/conf/nginx.conf`就是配置文件了 214 | -------------------------------------------------------------------------------- /JavaScript/原型与继承.md: -------------------------------------------------------------------------------- 1 | # 原型与继承 2 | ## 原型与原型链 3 | 4 | 5 | - `prototype`: 每个函数都有一个 prototype(原型)属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法,如果使用这个函数生成了实例,那么称这个对象为所有实例的原型。 6 | - `__proto__`: 每个对象都拥有 `__proto__` 属性,该属性用于实现原型链,当访问一个对象的属性时,如果该对象内部不存在这个属性,就通过原型链找直到找到或者到终点 null。 7 | - `constructor`:每个原型都有一个 constructor 属性指向关联的构造函数 8 | 9 | ## Object() 与 Function() 10 | 所有的对象都是由 Object() 构造函数构造的,所有的函数声明 / 函数表达式都是 Function() 构造函数的实例,而 Object() 构造函数本身又是 Function() 构造函数的实例,其原型关系如下: 11 | 12 | 13 | 14 | 需要注意的是 Function() 的 `__proto__ ` 属性直接指向的是其原型对象。 15 | 16 | 我们可以用下面的代码来验证这张图:在 node 环境及浏览器环境下都是一样的结果 17 | ```js 18 | console.log(Object.__proto__ === Function.prototype) // true 19 | console.log(Function.__proto__ === Function.prototype) // true 20 | console.log(Function.prototype.__proto__ === Object.prototype) // true 21 | console.log(Object.prototype.__proto__ === null) // true 22 | ``` 23 | ## 继承 24 | 首先要理解构造函数 new 时执行了哪些操作 25 | 1. 创建一个新对象(该对象的\_\_proto\_\_属性指向了构造函数的 prototype 属性指向的对象); 26 | 2. 将 this 绑定到这个新对象上 27 | 3. 执行构造函数中的代码(为这个新对象添加属性); 28 | 4. 返回新对象。(一般情况下,构造函数不返回值,但是用户可以选择主动返回对象,来覆盖正常的对象创建步骤) 29 | 30 | 31 | 模拟实现 new 32 | ```javaScript 33 | function _new(fn, ...args) { 34 | const obj = {} 35 | obj.__proto__ = fn.prototype 36 | fn.apply(obj, args) 37 | return Object.prototype.toString.call(obj) === '[object Object]' ? obj : {} 38 | } 39 | ``` 40 | 41 | 42 | ## 1.借用构造函数 43 | 在构造函数中 使用 Parent.call(this) 的方法继承父类属性。 44 | 45 | 原理: 将子类的 this 使用父类的构造函数跑一遍 46 | 47 | 缺点: Parent 原型链上的属性和方法并不会被子类继承(子类连接不到父类) 48 | ``` javaScript 49 | function Parent() { 50 | this.name = 'parent' 51 | } 52 | Parent.prototype.sayHello = function() { 53 | console.log('say Hello') 54 | } 55 | 56 | function Child() { 57 | Parent.call(this) // 函数名.call 调用这个函数但是更改其 this 58 | this.type = 'child' 59 | } 60 | let p1 = new Parent() 61 | let c1 = new Child() 62 | p1.sayHello() // 'say Hello' 63 | c1.sayHello() // error c1.sayHello is not a function 64 | ``` 65 | ## 2.原型链实现继承 66 | 原理:把子类的 prototype(原型对象)直接设置为父类的实例 67 | 68 | 缺点:因为子类只进行一次原型更改,所以子类的所有实例保存的是同一个父类的值。 69 | 当子类对象上进行值修改时,如果是修改的原始类型的值,那么会在实例上新建这样一个值; 70 | 但如果是引用类型的话,他就会去修改子类上唯一一个父类实例里面的这个引用类型,这会影响所有子类实例(一句话:子类修改原型上的引用类型会影响父类) 71 | 72 | 73 | ``` javaScript 74 | function Parent() { 75 | this.name = 'parent' 76 | this.arr = [1,2,3] 77 | } 78 | 79 | function Child() { 80 | this.type = 'child' 81 | } 82 | 83 | Child.prototype = new Parent() // 拥有了这个 Parent 实例上的属性和方法 84 | var c1 = new Child() 85 | var c2 = new Child() 86 | c1.__proto__ === c2.__proto__ // true 87 | console.log(Child.prototype.__proto__ === Parent.prototype) // true 88 | ``` 89 | 通过下面这个例子来观察该方法的缺点 90 | ```js 91 | function Parent () { 92 | this.names = ['kevin', 'daisy']; 93 | } 94 | 95 | function Child () { 96 | 97 | } 98 | 99 | Child.prototype = new Parent() 100 | 101 | var child1 = new Child() 102 | 103 | child1.names.push('yayu') 104 | 105 | console.log(child1.names); // ["kevin", "daisy", "yayu"] 106 | 107 | var child2 = new Child() 108 | 109 | console.log(child2.names) // ["kevin", "daisy", "yayu"] 110 | ``` 111 | ## 3.组合继承方式(上面两种方法的配合) 112 | 组合构造函数中使用 call 继承和原型链继承。 113 | 114 | 原理: 子类构造函数中使用 Parent.call(this) 的方式可以继承写在父类构造函数中this上绑定的各属性和方法; 115 | 使用 Child.prototype = new Parent() 的方式可以继承挂载在父类原型上的各属性和方法 116 | 117 | 118 | 缺点: 父类构造函数在子类构造函数中执行了一次,在子类绑定原型时又执行了一次 119 | ``` javaScript 120 | function Parent() { 121 | this.name = 'parent' 122 | this.arr = [1,2,3] 123 | } 124 | 125 | function Child() { 126 | Parent.call(this) // 继承 Parent 构造函数上的属性和方法 127 | this.type = 'child' 128 | } 129 | 130 | Child.prototype = new Parent(); // 继承 Parent 的父类原型上的属性和方法 131 | ``` 132 | ## 4.组合继承方式优化 133 | 使用 Object.create() 方法创建一个新对象,使用现有的对象(参数)来提供新创建的对象的\_\_proto\_\_ 134 | ``` javaScript 135 | function Parent() { 136 | this.name = 'parent' 137 | this.arr = [1,2,3] 138 | } 139 | 140 | function Child() { 141 | Parent.call(this) 142 | this.type = 'child' 143 | } 144 | Child.prototype = Object.create(Parent.prototype) // 提供__proto__ 145 | Child.prototype.constrctor = Child 146 | ``` 147 | 这种方式也叫寄生组合式继承,相比于之前的组合继承方式,其减少了一次父类构造函数的调用,如果不适用 Object.create() 方法,有时候也会这么封装: 148 | ```js 149 | function object(o) { 150 | function F() {} 151 | F.prototype = o 152 | return new F() 153 | } 154 | 155 | function prototype(child, parent) { 156 | var prototype = object(parent.prototype) 157 | prototype.constructor = child 158 | child.prototype = prototype 159 | } 160 | 161 | // 当我们使用的时候: 162 | prototype(Child, Parent) 163 | ``` 164 | ## 5.ES6实现继承 165 | ES6 的 Class 相当于构造函数的语法糖,extends 也是语法糖,其本质还是通过原型链实现继承 166 | ``` javaScript 167 | // Extends关键字配合Class实现继承 168 | class People { // 定义一个类People 169 | constructor(name) { // constructor函数,必须存在,接收实例化参数 170 | this.name = name 171 | } 172 | getName() { 173 | console.log(this.name) // 类的属性 174 | } 175 | } 176 | 177 | class Student extends People { // Student类继承People类 178 | constructor(name, grade) { // 声明constructor方法 179 | super(name) // 执行父类的构造函数 相当于People.prototype.constructor.call(this) 180 | this.grade = grade 181 | } 182 | getGrade() { // Student类的属性 183 | console.log(this.grade) 184 | } 185 | } 186 | let s = new Student('Tom', 6) // 实例化Student类 187 | s.getName() // 调用继承的属性,输出'Tom' 188 | s.getGrade() 189 | ``` 190 | ES5 的继承实质是先创造子类的实例对象 this,然后再将父类的方法添加到 this 上面。ES6的继承机制是先创造父类的实例对象 this(所以必须先调用 super 方法),然后再将子类的构造函数修改 this 191 | 192 | ES5 的寄生组合式继承: 193 | ```js 194 | function Parent (name) { 195 | this.name = name 196 | } 197 | 198 | function Child (name, age) { 199 | Parent.call(this, name) 200 | this.age = age 201 | } 202 | 203 | Child.prototype = Object.create(Parent.prototype) 204 | 205 | var child1 = new Child('kevin', '18') 206 | 207 | console.log(child1) 208 | ``` 209 | 对应的 ES6 的 class: 210 | ```js 211 | class Parent { 212 | constructor(name) { 213 | this.name = name 214 | } 215 | } 216 | 217 | class Child extends Parent { 218 | constructor(name, age) { 219 | super(name) // 调用父类的 constructor(name) 220 | this.age = age 221 | } 222 | } 223 | 224 | let child1 = new Child('kevin', '18') 225 | 226 | console.log(child1) 227 | ``` 228 | 对应的原型链示意图为: 229 | 230 | 231 | 232 | -------------------------------------------------------------------------------- /服务器/Linux 基础.md: -------------------------------------------------------------------------------- 1 | # 包管理工具 2 | RPM 和 DPKG 为最常见的两类软件包管理工具: 3 | - RPM 全称为 Redhat Package Manager,最早由 Red Hat 公司制定实施,随后被 GNU 开源操作系统接受并成为很多 Linux 系统 (RHEL) 的既定软件标准。 4 | - 与 RPM 竞争的是基于 Debian 操作系统 (Ubuntu) 的 DEB 软件包管理工具 DPKG,全称为 Debian Package,功能方面与 RPM 相似。 5 | 6 | YUM 基于 RPM,具有依赖管理和软件升级功能。 7 | 8 | # VIM三个模式 9 | - 一般指令模式(Command mode):VIM 的默认模式,可以用于移动游标查看内容; 10 | - 编辑模式(Insert mode):按下 "i" 等按键之后进入,可以对文本进行编辑; 11 | - 指令列模式(Bottom-line mode):按下 ":" 按键之后进入,用于保存退出等操作。 12 | 13 | 14 | 15 | 在指令列模式下,有以下命令用于离开或者保存文件。 16 | 17 | | 命令 | 作用 | 18 | | - | -| 19 | | :w | 写入磁盘 | 20 | | :w! | 当文件为只读时,强制写入磁盘。到底能不能写入,与用户对该文件的权限有关 | 21 | | :q | 离开 | 22 | | :q! | 强制离开不保存 | 23 | | :wq | 写入磁盘后离开 | 24 | | :wq! | 强制写入磁盘后离开 | 25 | 26 | # 常用指令 27 | ## 压缩与打包 28 | Linux 底下有很多压缩文件名,常见的如下: 29 | 30 | | 扩展名 | 压缩程序 | 31 | | --- | --- | 32 | | \*.Z | compress | 33 | | \*.zip | zip | 34 | | \*.gz | gzip | 35 | | \*.bz2 | bzip2 | 36 | | \*.xz | xz | 37 | | \*.tar | tar 程序打包的数据,没有经过压缩 | 38 | | \*.tar.gz | tar 程序打包的文件,经过 gzip 的压缩 | 39 | | \*.tar.bz2 | tar 程序打包的文件,经过 bzip2 的压缩 | 40 | | \*.tar.xz | tar 程序打包的文件,经过 xz 的压缩 | 41 | 42 | ### 压缩指令 43 | 1\. gzip 44 | gzip 是 Linux 使用最广的压缩指令,可以解开 compress、zip 与 gzip 所压缩的文件。 45 | 46 | 经过 gzip 压缩过,源文件就不存在了。 47 | 48 | 有 9 个不同的压缩等级可以使用。 49 | 50 | 可以使用 zcat、zmore、zless 来读取压缩文件的内容。 51 | 52 | ```shell 53 | $ gzip [-cdtv#] filename 54 | -c :将压缩的数据输出到屏幕上 55 | -d :解压缩 56 | -t :检验压缩文件是否出错 57 | -v :显示压缩比等信息 58 | -# : # 为数字的意思,代表压缩等级,数字越大压缩比越高,默认为 6 59 | ``` 60 | 61 | 2\. bzip2 62 | 63 | 提供比 gzip 更高的压缩比。 64 | 65 | 查看命令:bzcat、bzmore、bzless、bzgrep。 66 | 67 | ```shell 68 | $ bzip2 [-cdkzv#] filename 69 | -k :保留源文件 70 | ``` 71 | 72 | 3\. xz 73 | 74 | 提供比 bzip2 更佳的压缩比。 75 | 76 | 可以看到,gzip、bzip2、xz 的压缩比不断优化。不过要注意的是,压缩比越高,压缩的时间也越长。 77 | 78 | 查看命令:xzcat、xzmore、xzless、xzgrep。 79 | 80 | ```shell 81 | $ xz [-dtlkc#] filename 82 | ``` 83 | ### 打包 84 | 压缩指令只能对一个文件进行压缩,而打包能够将多个文件打包成一个大文件。tar 不仅可以用于打包,也可以使用 gzip、bzip2、xz 将打包文件进行压缩。 85 | 86 | ```shell 87 | $ tar [-z|-j|-J] [cv] [-f 新建的 tar 文件] filename... ==打包压缩 88 | $ tar [-z|-j|-J] [tv] [-f 已有的 tar 文件] ==查看 89 | $ tar [-z|-j|-J] [xv] [-f 已有的 tar 文件] [-C 目录] ==解压缩 90 | 91 | -z :使用 zip; 92 | -j :使用 bzip2; 93 | -J :使用 xz; 94 | -c :新建打包文件; 95 | -t :查看打包文件里面有哪些文件; 96 | -x :解打包或解压缩的功能; 97 | -v :在压缩/解压缩的过程中,显示正在处理的文件名; 98 | -f : filename:要处理的文件; 99 | -C 目录 : 在特定目录解压缩。 100 | ``` 101 | 102 | | 使用方式 | 命令 | 103 | | -| - | 104 | | 打包压缩 | tar -jcv -f filename.tar.bz2 要被压缩的文件或目录名称 | 105 | | 查看 | tar -jtv -f filename.tar.bz2 | 106 | | 解压缩 | tar -jxv -f filename.tar.bz2 -C 要解压缩的目录 | 107 | 108 | ## 管道指令 109 | 管道是将一个命令的标准输出作为另一个命令的标准输入,在数据需要经过多个步骤的处理之后才能得到我们想要的内容时就可以使用管道。 110 | 111 | 在命令之间使用 | 分隔各个管道命令。 112 | 113 | ```shell 114 | $ ls -al /etc | less 115 | ``` 116 | 117 | ## 进程管理 118 | 1\. ps 119 | 查看某个时间点的进程信息 120 | 121 | 示例一:查看自己的进程 122 | ```hell 123 | $ ps -l 124 | ``` 125 | 示例二:查看系统所有进程 126 | 127 | ```shell 128 | $ ps aux 129 | ``` 130 | 示例三:查看特定的进程 131 | 132 | ```shell 133 | $ ps aux | grep threadx 134 | ``` 135 | 2\. pstree 136 | 137 | 查看进程树 138 | 139 | 示例:查看所有进程树 140 | ```shell 141 | $ pstree -A 142 | ``` 143 | 3\. top 144 | 145 | 实时显示进程信息 146 | 147 | 示例:两秒钟刷新一次 148 | ```shell 149 | $ top -d 2 150 | ``` 151 | 4\. netstat 152 | 153 | 查看占用端口的进程 154 | 155 | 示例:查看特定端口的进程 156 | ```shell 157 | $ netstat -anp | grep port 158 | ``` 159 | 其他示例 160 | ```shell 161 | $ ps -ef 显示当前所有进程环境变量及进程间关系 162 | $ ps -A 显示当前所有进程 163 | $ ps -aux | grep apache 与 grep 联用查找某进程 164 | $ ps aux | grep '(cron|syslog)' 找出与 cron 与 syslog 这两个服务有关的 PID 号码 165 | ``` 166 | ## 文件查找 167 | find 搜索文件的命令格式 168 | 169 | find \[搜索范围\] \[匹配条件\] 170 | 171 | 选项: 172 | - name 根据名字查找 173 | - size    根据文件大小查找, +, -\: 大于设置的大小,直接写大小是等于 174 | - user   查找用户名的所有者的所有文件 175 | - group 根据所属组查找相关文件 176 | - type    根据文件类型查找(f 文件,d 目录,l 软链接文件) 177 | - inum   根据 i 节点查找 178 | - amin   访问时间 access 179 | - cmin    文件属性 change 180 | - mmin   文件内容 modify 181 | 182 | 示例: 183 | 184 | ``` shell 185 | $ find / -name filename.txt 根据名称查找/目录下的 filename.txt 文件。 186 | $ find . -name "*.xml" 递归查找所有的xml文件 187 | $ find . -name "*.xml" |xargs grep "hello world" 递归查找所有文件内容中包含 hello world的 xml 文件 188 | $ grep -H 'spring'*.xml 查找所以有的包含 spring 的 xml 文件 189 | $ find ./ -size 0 | xargs rm -f & 删除文件大小为零的文件 190 | ``` 191 | ## 日常操作 192 | 查看文件: ls ll 193 | 194 | 进入目录: cd 195 | 196 | 显示当前路径: pwd 197 | 198 | 创建文件夹: mkdir 文件名 199 | 200 | rm: 删除 ,删除以 -f 开头的文件 rm -- -f* 201 | 202 | mv:重命名&移动文件 203 | - 将文件 test.log 重命名为 test1.txt 204 | ```shell 205 | $ mv test.log test1.txt 206 | ``` 207 | 208 | - 将文件 log1.txt,log2.txt,log3.txt 移动到根的 test3 目录中 209 | ```shell 210 | $ mv llog1.txt log2.txt log3.txt /test3 211 | ``` 212 | - 将文件 file1 改名为 file2,如果 file2 已经存在,则询问是否覆盖 213 | ```shell 214 | $ mv -i log1.txt log2.txt 215 | ``` 216 | - 移动当前文件夹下的所有文件到上一级目录 217 | ```shell 218 | $ mv * ../ 219 | ``` 220 | 221 | 222 | cp:复制 223 | 224 | 将源文件复制至目标文件,或将多个源文件复制至目标目录。 225 | 226 | 注意:命令行复制,如果目标文件已经存在会提示是否覆盖,而在 shell 脚本中,如果不加 \-i 参数,则不会提示,而是直接覆盖! 227 | ```shell 228 | -i 提示 229 | -r 复制目录及目录内所有项目 230 | -a 复制的文件与原文件时间一样 231 | ``` 232 | 实例: 233 | 234 | 1)复制 a.txt 到 test 目录下,保持原文件时间,如果原文件存在提示是否覆盖 235 | ```shell 236 | $ cp -ai a.txt test 237 | ``` 238 | 2)为 a.txt 建立一个链接(快捷方式) 239 | ```shell 240 | $ cp -s a.txt link_a.txt 241 | ``` 242 | 243 | sudo chmod -R 777 目录名 244 | 245 | -R 是指级联应用到目录里的所有子目录和文件 246 | 247 | 777 是所有用户都拥有最高权限(可自定权限码) 248 | 249 | 250 | # 关键操作记录 251 | 1.如何找到一个占用某个端口的后台进程并关闭这个进程? 252 | 253 | 使用`netstat -tunlp`查看端口被占用的情况,可以看到占用端口的进程的PID 254 | 255 | 256 | 257 | 然后使用`kill pid`命令杀死这个进程即可 258 | 259 | `netstat -tunlp|grep 端口号`这个命令可以直接找到占用对应端口的进程 260 | 261 | ***** 262 | 2.使用 curl 进行网络检测 263 | 264 | curl 是一个发送请求的命令行工具。可使用 HTTP(s)、FTP,以及一些你可能从未听过的协议发送请求。它可以下载文件,检查响应头,自由地访问远程数据。 265 | 266 | 示例: 267 | 268 | 1)获取一个 URL 的 HTTP HEADER 269 | ```shell 270 | $ curl -I http://google.com 271 | HTTP/1.1 302 Found 272 | Cache-Control: private 273 | Content-Type: text/html; charset=UTF-8 274 | Referrer-Policy: no-referrer 275 | Location: http://www.google.com/?gfe_rd=cr&ei=0fCKWe6HCZTd8AfCoIWYBQ 276 | Content-Length: 258 277 | Date: Wed, 09 Aug 2017 11:24:01 GMT 278 | ``` 279 | 2)向远程API发出GET请求 280 | ```shell 281 | $ curl http://numbersapi.com/random/trivia 282 | ``` 283 | ***** 284 | 3.使用 tree 展示文件目录结构 285 | 286 | [每个 web 开发者都应该了解的 12 个命令行](https://blog.csdn.net/powertoolsteam/article/details/90764150#comments) 287 | -------------------------------------------------------------------------------- /JavaScript/作用域、作用域链与闭包.md: -------------------------------------------------------------------------------- 1 | # 作用域、作用域链、闭包 2 | ## 作用域和作用域链 3 | 作用域和作用域链,简单来说只要记住以下几个点: 4 | - 作用域最大的用处是隔离变量,不同作用域下同名变量不会冲突。 5 | - 作用域是分层的,内层作用域可以访问外层作用域的变量,反之则不行。 6 | - 作用域链用于标识符解析。标识符解析是沿着作用域链一级一级地搜索标识符的过程。搜索过程始终从作用域链的前端开始,然后逐级地向后回溯,直至找到标识符为止(如果找不到标识符,通常会导致错误发生)。 7 | 8 | 从编译原理的角度来讲,JavaScript 引擎会在代码执行前对其进行编译,在这个过程中,像 var a = 2 这样的声明会被分解为两个独立的步骤: 9 | 10 | 1. 首先,var a 在其作用域中声明新变量。这会在最开始的阶段,也就是代码执行前进行。 11 | 12 | 2. 接下来,a = 2 会查询(LHS 查询)变量 a 并对其进行赋值,查询是沿着作用域链进行的。 13 | 14 | ## 词法作用域、函数作用域、块作用域 15 | 上面大致介绍了作用域和作用域链的用途,下面对其进行更深入的分析。 16 | ### 词法作用域 17 | 简单来说,词法作用域就是定义在词法阶段的作用域(大部分编译器都有词法分析这一阶段),即词法作用域是由你在写代码时将变量和块作用域写在哪里来决定的。 18 | 在《你不知道的 JavaScript》中举了这么一个例子: 19 | ```js 20 | function foo (a) { 21 | var b = a * 2 22 | 23 | function bar (c) { 24 | console.log(a, b, c) 25 | } 26 | 27 | bar(b * 3) 28 | } 29 | 30 | foo(2) // 2, 4, 12 31 | ``` 32 | 这个例子中有三个逐级嵌套的作用域,可以将它们想象成几个逐级包含的气泡。 33 | 34 | 35 | 36 | ❶ 包含着整个全局作用域,其中只有一个标识符:foo 37 | 38 | ❷ 包含着 foo 所创建的作用域,其中有三个标识符:a、bar 和 b 39 | 40 | ❸ 包含着 bar 所创建的作用域,其中只有一个标识符:c 41 | 42 | 43 | 显然,这些气泡的排列顺序是在书写代码时决定的,那么什么会产生一个新的气泡?只有函数会生成新的气泡吗? 44 | 45 | 对于 JavaScript 而言,每声明一个函数确实会为其自身创建一个气泡,但是需要注意的是除了函数之外其他结构也能创建作用域气泡,比如 with、try / catch、以及 let 声明对应的块作用域。 46 | 47 | ### 函数作用域 48 | 函数作用域的含义是:属于这个函数的全部变量都可以在整个函数的范围内使用及复用。 49 | 50 | 函数声明与函数表达式:函数声明是不可以省略函数名的,而函数表达式可以 51 | ```js 52 | function foo (a) { 53 | console.log('function') 54 | } 55 | 56 | setTimeout(function () { 57 | console.log('I waited 1 second') 58 | }, 1000) 59 | ``` 60 | 另外,需要注意的是立即执行函数表达式(IIFE - Immediately Invoked Function Expression)的作用域问题: 61 | ```js 62 | var a = 2; // 加分号...否则编译报错 63 | 64 | (function foo () { 65 | var a = 3 66 | console.log(a) // 3 67 | console.log(foo) // [Function: foo] 68 | })() 69 | 70 | console.log(a) // 2 71 | console.log(foo) // ReferenceError: foo is not defined 72 | ``` 73 | 由于函数被包含在一对()括号内部,因此成为了一个函数表达式,通过在末尾加上另外一个()可以立即执行这个函数。这种形式让 foo 变量名隐藏在自身中而不会非必要地污染外部作用域。 74 | 75 | ### 块作用域 76 | 除 JavaScript 外的很多编程语言都支持块作用域,块作用域的用处就是让变量的声明距离其使用的地方尽可能的近,通常是将变量绑定到所在的 {...} 中。 77 | ```js 78 | var foo = true 79 | 80 | if (foo) { 81 | var bar = foo * 2 82 | } 83 | 84 | console.log(bar) // 2 85 | ``` 86 | bar 变量仅在 if 声明的上下文中使用,因此如果能将它声明在 if 块内部将会是一个非常有意义的事情,ES6 的 let 关键字就很好地解决了这个问题。 87 | ```js 88 | var foo = true 89 | 90 | if (foo) { 91 | let bar = foo * 2 92 | } 93 | 94 | console.log(bar) // ReferenceError: bar is not defined 95 | ``` 96 | 另一个常见的问题就是 for 循环: 97 | ```js 98 | for (var i = 0; i < 10; i++) { 99 | 100 | } 101 | console.log(i) // 10 102 | 103 | for (let j = 0; j < 10; j++) { 104 | 105 | } 106 | console.log(j) // ReferenceError: j is not defined 107 | ``` 108 | 109 | 110 | ## 闭包 111 | 函数 A 返回了一个函数 B,并且函数 B 中使用了函数 A 的变量,就形成了闭包。 112 | 113 | 理解闭包的关键在于:**内部函数的作用域链中包含外部函数的作用域(本身作用域的上一级)**。 114 | 115 | 《JavaScript高级程序设计》的这个例子十分清晰地解释了闭包 116 | ``` js 117 | function createComparisonFunction(propertyName) { 118 | return function(object1, object2) { 119 | var value1 = object1[propertyName] 120 | var value2 = object2[propertyName] 121 | 122 | if (value1 < value2) { 123 | return -1 124 | } else if (value1 > value2) { 125 | return 1 126 | } else { 127 | return 0 128 | } 129 | } 130 | } 131 | // 创建函数 132 | var compareNames = createComparisonFunction('name') 133 | // 调用函数 134 | var result = compareNames({name: 'Nicholas'}, {name: 'Greg'}) 135 | // 解除对匿名函数的引用(以便释放内存) 136 | compareNames = null 137 | ``` 138 | 139 | ![](https://box.kancloud.cn/74828145b5958c9eb5479f5300c8c2f4_730x409.png) 140 | 141 | 142 | 这个图涉及到了**执行环境**、**变量对象**、**活动对象**、**作用域链** 等概念,同时这张图也用于解释**闭包** 143 | 144 | 145 | **执行环境(execution context)**:执行环境定义了变量或函数有权访问的其他数据 146 | - 全局执行环境是最外围的一个执行环境,在Web浏览器中被认为是 window 对象,因此所有全局变量和函数都是作为 window 对象的属性和方法创建的 147 | - 每个函数都有自己的执行环境 148 | - 当执行流进入一个函数时,函数的环境就会被推入一个环境栈中。 而在函数执行之后,栈将其环境弹出,把控制权返回给之前的执行环境。ECMAScript 程序中的执行流正是由这个方便的机制控制着。 149 | 150 | **变量对象(variable object)**:每个执行环境都有一个与之关联的变量对象,环境中定义的所有变量和函数都保存在这个对象中。虽然我们编写的代码无法访问这个对象,但解析器在处理数据时会在后台使用它。 151 | 152 | 153 | **活动对象(activation object)**:执行环境为函数,则其活动对象为变量对象 154 | 155 | 156 | **作用域链(scope chain)**:当代码在一个环境中执行时,会创建变量对象的一个作用域链。作用域链的用途,是保证对执行环境有权访问的所有变量和函数的有序访问。 157 | 158 | 冴羽大大对这几个概念做了深入的分析:点击跳转 159 | ***** 160 | 理解闭包的关键在于:**内部函数的作用域链中包含(本身作用域的上一级)外部函数的作用域**,再观察下上面的图,就是说内部函数对外部函数的活动对象有引用,所以即使外部函数出栈了,其活动对象任然驻留在内存中。 161 | 162 | 因此,闭包不能滥用,其会导致内存泄漏,影响网页的性能。闭包使用完之后,要立即释放资源,将引用变量指向 null,这等同于通知垃圾回收例程将其清除。 163 | 164 | ### 闭包中的 this 165 | 在闭包中使用 this 对象也可能会导致一些问题。我们知道,this 对象是在运行时基于函数的执行环境绑定的:**在全局函数中,this 等于 window,而当函数被作为某个对象的方法调用时,this 等于那个对象**。不过,匿名函数的执行环境具有全局性(见 this 的绑定规则部分),因此其 this 对象通常指向 window。下面来看一个例子 166 | ```js 167 | var name = "The Window"; 168 | var object = { 169 | name : "My Object", 170 | getNameFunc : function(){ 171 | return function(){ 172 | return this.name; 173 | }; 174 | } 175 | }; 176 | console.log(object.getNameFunc()()); //"The Window"(在非严格模式下) 177 | // node.js环境下是undefined 178 | ``` 179 | 按照之前的对闭包的解释会有如下一个问题,为什么匿名函数没有取得其包含作用域(或外部作用域)的 this 对象呢? 180 | 181 | 每个函数在被调用时都会自动取得两个特殊变量:this 和 arguments。内部函数在搜索这两个变量时,**只会搜索到其活动对象为止,因此永远不可能直接访问外部函数中的这两个变量**。不过,把外部作用域中的 this 对象保存在一个闭包能够访问到的变量里,就可以让闭包访问该对象了,如下所示。 182 | ``` javaScript 183 | var name = "The Window"; 184 | var object = { 185 | name: "My Object", 186 | getNameFunc: function() { 187 | var that = this; 188 | return function() { 189 | return that.name; 190 | }; 191 | } 192 | }; 193 | console.log(object.getNameFunc()()) // My Object 194 | ``` 195 | 196 | ### 闭包的用途 197 | 一句话回顾下闭包的定义:函数 A 返回了一个函数 B,并且函数 B 中使用了函数 A 的变量,就形成了闭包。其大致有以下用途: 198 | 1. 可以读取函数内部的变量。 199 | 2. 可以使变量的值长期保存在内存中 200 | 3. 可以用来实现JS模块。 201 | 4. 模仿块级作用域 202 | 5. 实现私有变量 203 | 204 | ``` javaScript 205 | // 匿名闭包:IIFE 206 | var Module = (function () { 207 | var _private = 'safe now' 208 | var foo = function () { 209 | console.log(_private) 210 | } 211 | return { 212 | foo: foo 213 | } 214 | })() 215 | 216 | Module.foo() // safe now 217 | console.log(Module._private) // undefined 218 | ``` 219 | [IIFE](https://developer.mozilla.org/zh-CN/docs/Glossary/%E7%AB%8B%E5%8D%B3%E6%89%A7%E8%A1%8C%E5%87%BD%E6%95%B0%E8%A1%A8%E8%BE%BE%E5%BC%8F) 220 | 221 | 222 | 什么样的代码才能称为 JS 模块呢? 223 | 具有特定功能的 JS 文件,将所有的数据和功能都封装在一个函数内部(私有的),只向外暴露一个包含 n 个方法的对象或函数,模块的使用者,只需要通过模块暴露的对象调用方法来实现对应的功能。 224 | 另外函数节流与防抖也用到了闭包,可以参看 JS-Coding 章节。 225 | ### 例题 226 | ``` javaScript 227 | function outer() { 228 | var num=0 // 内部变量 229 | return function add() { // 通过 return 返回 add 函数,就可以在 outer 函数外访问了 230 | num++ // 内部函数有引用,作为 add 函数的一部分了 231 | console.log(num) 232 | } 233 | } 234 | var func1 = outer() 235 | func1() // 实际上是调用 add 函数, 输出1 236 | func1() // 输出2 因为 outer 函数内部的私有作用域会一直被占用 237 | var func2 = outer() 238 | func2() // 输出1 每次重新引用函数的时候,闭包是全新的。 239 | func2() // 输出2 240 | ``` 241 | -------------------------------------------------------------------------------- /JavaScript/基础概念.md: -------------------------------------------------------------------------------- 1 | # 基本概念 2 | 7 种数据类型: `Null、Undefined、Number、Boolean、String、Object、Symbol` 3 | 4 | 排除 Symbol 的话,高程中将 Undefined、Null、Number、Boolean、String 定义为基本数据类型,因为其是按值访问的,可以操作保存在变量中的实际的值。引用类型值 5 | 是保存在内存中的对象,操作对象时,实际上操作的是对象的引用。 6 | 7 | [js 中的值类型和引用类型的区别](https://www.cnblogs.com/leiting/p/8081413.html) 8 | 9 | 如何判断变量的数据类型?使用`typeof`运算符: 10 | * typeof 对于基本类型,除了 null 都可以显示正确的类型 11 | * typeof 对于对象,除了函数都会显示 object 12 | * 对于 null 来说,虽然它是基本类型,但是会显示 object,这是一个存在很久了的 Bug 13 | 14 | ```javaScript 15 | typeof 1 // 'number' 16 | typeof '1' // 'string' 17 | typeof undefined // 'undefined' 18 | typeof true // 'boolean' 19 | typeof Symbol() // 'symbol' 20 | typeof b // b没有声明,但是还会显示undefined 21 | 22 | typeof [] // 'object' 23 | typeof {} // 'object' 24 | typeof console.log // 'function' 25 | typeof null // 'object' 26 | ``` 27 | 28 | 使用`Object.prototype.toString.call()`,该方法返回类似[object Type]形式的字符串 29 | ```javaScript 30 | let a = [] 31 | let b = {} 32 | let c = true 33 | let d = 'string' 34 | let e = null 35 | let f = undefined 36 | let g = 1 37 | let h = function () {} 38 | let i = Symbol('symbol') 39 | console.log(Object.prototype.toString.call(a)) // [object Array] 40 | console.log(Object.prototype.toString.call(b)) // [object Object] 41 | console.log(Object.prototype.toString.call(c)) // [object Boolean] 42 | console.log(Object.prototype.toString.call(d)) // [object String] 43 | console.log(Object.prototype.toString.call(e)) // [object Null] 44 | console.log(Object.prototype.toString.call(f)) // [object Undefined] 45 | console.log(Object.prototype.toString.call(g)) // [object Number] 46 | console.log(Object.prototype.toString.call(h)) // [object Function] 47 | console.log(Object.prototype.toString.call(i)) // [object Symbol] 48 | console.log('[object Array]' === Object.prototype.toString.call(a)) // true 49 | ``` 50 | 51 | # if 条件判断时的注意事项 52 | 53 | | 数据类型 | 转换为true的值 | 转换为false的值 | 54 | | :---- | :---- | :---- | 55 | | Boolean | true | false | 56 | | String | 任何非空字符串 | "" (空字符串) | 57 | | Number| 任何非零数字值(包括无穷大) | 0和NaN | 58 | | Object| 任何对象 | null | 59 | | Undefined| n/a(不适用) | undefined | 60 | 61 | **逻辑非** 62 | - 如果操作数是一个对象,返回 false 63 | - 如果操作数是一个空字符串,返回 true 64 | - 如果操作数是一个非空字符串,返回 false 65 | - 如果操作数是数值0,返回 true 66 | - 如果操作数是任意非0的值(包括 Infinity),返回 false 67 | - 如果操作数是 null,返回 true 68 | - 如果操作数是 NaN,返回 true 69 | - 如果操作数是 undefined,返回 true 70 | 71 | # 四则运算注意事项 72 | 只有当**加法运算**时,其中一方是字符串类型,就会把另一个也转为字符串类型。其他运算只要其中一方是数字,那么另一方就转为数字。并且加法运算会触发三种类型转换:将值转换为原始值,转换为数字,转换为字符串。 73 | ```javaScript 74 | 1 + '1' // '11' 75 | 2 * '2' // 4 76 | [1, 2] + [2, 1] // '1,22,1' 77 | // [1, 2].toString() -> '1,2' 78 | // [2, 1].toString() -> '2,1' 79 | // '1,2' + '2,1' = '1,22,1' 80 | ``` 81 | 对于加号需要注意这个表达式`'a' + + 'b'` 82 | ```js 83 | 'a' + + 'b' // -> "aNaN" 84 | // 因为 + 'b' -> NaN 85 | // 你也许在一些代码中看到过 + '1' -> 1 86 | ``` 87 | 88 | # toString() 方法的使用 89 | 数值、布尔值、对象和字符串值(没错,每个字符串也都有一个 toString() 方法,该方法返回字符串的一个副本)都有 toString() 方法。但 null 和 undefined 值没有这个方法。 90 | 91 | 92 | 多数情况下,调用 toString() 方法不必传递参数。但是,在调用数值的 toString() 方法时,可以传递一个参数:输出数值的基数。默认情况下,toString() 方法以十进制格式返回数值的字符串表示。而通过传递基数,toString() 可以输出以二进制、八进制、十六进制,乃至其他任意有效进制格式表示的字符串值。下面给出几个例子: 93 | ```js 94 | var num = 10 95 | alert(num.toString()) // "10" 96 | alert(num.toString(2)) // "1010" 97 | alert(num.toString(8)) // "12" 98 | alert(num.toString(10)) // "10" 99 | alert(num.toString(16)) // "a" 100 | ``` 101 | 102 | # 变量、函数提升 103 | 在生成执行上下文时,会有两个阶段。第一个阶段是创建的阶段,JS 解释器会找出需要提升的变量和函数,并且给他们提前在内存中开辟好空间,函数的话会将整个函数存入内存中,变量只声明并且赋值为 undefined。在第二个阶段,也就是代码执行阶段,我们可以直接提前使用。**在提升的过程中,同名的函数会覆盖上一个函数,并且函数优先于变量提升** 104 | 105 | 106 | 简而言之:由于变量提升,使用 var 声明的变量声明前使用则值为 undefined(本作用域下),函数可以在声明之前就使用。 107 | ``` javaScript 108 | b() // call b 109 | console.log(a) // undefined 110 | var a = 'Hello world' 111 | function b() { 112 | console.log('call b') 113 | } 114 | var b = 'I am a var' 115 | ``` 116 | 117 | # instanceof 118 | instanceof 运算符用于测试构造函数的 prototype 属性是否出现在对象的原型链中的任何位置。 119 | 用法:`对象 instanceof 构造函数` 120 | ```javaScript 121 | function Car(make, model, year) { 122 | this.make = make 123 | this.model = model 124 | this.year = year 125 | } 126 | var auto = new Car('Honda', 'Accord', 1998) 127 | 128 | console.log(auto instanceof Car) 129 | // expected output: true 130 | 131 | console.log(auto instanceof Object) 132 | // expected output: true 133 | ``` 134 | 135 | # Object 对象 136 | 参考:[https://www.jb51.net/article/80177.htm](https://www.jb51.net/article/80177.htm) 137 | **对象实例的一些方法** 138 | - hasOwnProperty(propertyName):接收一个字符串参数,该参数表示属性名称,用来判断该属性是否在当前对象实例中,而不是在对象的原型链中。 139 | ```js 140 | var arr = [] 141 | console.log(arr.hasOwnProperty("length")) // true 142 | console.log(arr.hasOwnProperty("hasOwnProperty")) // false 143 | // length 是 arr 自己的属性,而 hasOwnProperty 是原型链上的属性(方法) 144 | ``` 145 | - isPrototypeOf(Object):isPrototype方法接收一个对象,用来判断当前对象是否在传入的参数对象的原型链上。关于原型链可参考原型与继承章节。 146 | ``` 147 | function MyObject() {} 148 | var obj = new MyObject() 149 | console.log(Object.prototype.isPrototypeOf(obj)) // true 150 | ``` 151 | - toString():返对象的字符串表示 152 | - valueOf():返回对象的原始值,可能是字符串、数值、bool 值等,看具体的对象 153 | 154 | **特性操作的相关方法:** 155 | - Object.defineProperty(obj, propName, descriptor):接收三个参数,obj 是需要定义属性的对象,propName 是需要被定义的属性名,descriptor 是属性描述符,包含一些属性的特性定义 156 | ```js 157 | var obj = {} 158 | Object.defineProperty(obj, "name", { 159 | value: "name", 160 | configurable: true, 161 | writable: true, 162 | enumerable: true 163 | }) 164 | ``` 165 | - Object.defineProperties():与 defineProperty 不同之处在于可以同时定义多个属性 166 | ```js 167 | var obj = {}; 168 | Object.defineProperty(obj, { 169 | "name": { 170 | value: "name", 171 | configurable: true, 172 | writable: true, 173 | enumerable: true 174 | }, 175 | "age": { 176 | value: 20 177 | } 178 | }) 179 | ``` 180 | - Object.getOwnPropertyDescriptor(obj, propName):用于读取特性值,接收对象及其属性名两个参数,返回一个对象 181 | ``` 182 | var person = { 183 | _age: 10, 184 | type: "小孩" 185 | } 186 | Object.defineProperty(person, "age", { 187 | get: function () { 188 | return this._age 189 | }, 190 | set: function (newValue) { 191 | this._age = newValue 192 | this.type = newValue > 17 ? "成人" : "小孩" 193 | } 194 | }) 195 | 196 | console.log(Object.getOwnPropertyDescriptor(person, "type")) 197 | // Object {value: "成人", writable: true, enumerable: true, configurable: true} 198 | console.log(Object.getOwnPropertyDescriptor(person, "age")) 199 | // Object {enumerable: false, configurable: false, get: function(),set: function ()} 200 | ``` 201 | **其他:** 202 | - Object.getOwnPropertyNames():用于获取对象自身的所有属性,包括可枚举和不可枚举的所有属性,返回一个数组 203 | ```js 204 | function Parent() { 205 | this.lastName = "Black" 206 | } 207 | function Child(firstName) { 208 | this.firstName = firstName 209 | } 210 | Child.prototype = new Parent() 211 | 212 | var son = new Child("Jack"); 213 | Object.defineProperty(son, "age", { 214 | enumerable: false 215 | }) 216 | console.log(Object.keys(son)) // ["firstName"] 217 | console.log(Object.getOwnPropertyNames(son)) // ["firstName", "age"] 218 | ``` 219 | - Object.keys():用于获取给定对象的所有可枚举的自身属性的属性名,它返回一个数组,例子如上 220 | -------------------------------------------------------------------------------- /CSS/常见问题1.md: -------------------------------------------------------------------------------- 1 | # link 标签和 @import 的区别 2 | * link 属于 html 标签,而 @import 是 css 提供的 3 | * 页面被加载时,link 会同时被加载,而 @import 引用的 css 会等到页面加载结束后加载。 4 | * link 是 html 标签,因此没有兼容性,而 @import 只有 IE5 以上才能识别。 5 | * link 方式样式的权重高于 @import 的 6 | 7 | 简而言之,使用 @import 的关键点在于其可以先加载 HTML,后加载 CSS;另外,如果要动态的添加 CSS 样式的话(比如切换主题的实现)还是得用 link 标签; 8 | 另外,我们写 sass 时也是使用 @import "mixin.scss" 而不是 link "mixin.scss" 9 | 10 | # BFC 及其应用 11 | **定义** 12 | 13 | 14 | BFC(Block formatting context) 直译为"块级格式化上下文"。它是一个独立的渲染区域,只有 Block-level box 参与, 15 | 它规定了内部的 Block-level Box 如何布局,并且与这个区域外部毫不相干。 16 | 17 | 18 | **生成** 19 | 20 | 21 | CSS2.1中规定满足下列 CSS 声明之一的元素便会生成 BFC。 22 | 1. 根元素 23 | 2. float 的值不为 none 24 | 3. overflow 的值不为 visible 25 | 4. display 的值为 inline-block、table-cell、table-caption 中的任何一个; display:table 也认为可以生成 BFC, 26 | 其实这里的主要原因在于 table 会默认生成一个匿名的 table-cell,正是这个匿名的 table-cell 生成了 BFC 27 | 5. position 的值为 absolute 或 fixed 28 | 29 | 30 | **约束** 31 | 1. 内部的 Box 会在垂直方向上一个接一个的放置 32 | 2. 属于同一个 BFC 的两个相邻 Box 的 margin 会发生重叠(塌陷),与方向无关。(重叠后的 margin 取大者) 33 | 3. 每个元素的左外边距与包含块的左边界相接触(从左向右),即使浮动元素也是如此。(这说明 BFC 中子元素不会超出他的包含块,而 position 为 absolute 的元素可以超出他的包含块边界) 34 | 4. BFC 的区域不会与 float 的元素区域重叠 35 | 5. 计算 BFC 的高度时,浮动子元素也参与计算 36 | 6. BFC 就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面元素,反之亦然 37 | 38 | 39 | **应用** 40 | - 解决垂直和水平方向上 margin 重叠,一般设置 overflow:hidden 41 | - 清除内部浮动(根据规则5 -“计算BFC的高度时,浮动元素也参与计算”) 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | ## 内联元素与块级元素 50 | 51 | 52 | **块级元素**:记忆方式(H5 语义化标签、p、div、h 标题) 53 | 54 | 55 | | 标签 | 用途 | 标签 | 用途 | 56 | | :---- | :---- |:---- | :---- | 57 | |\| 联系方式信息| \
| 文章内容| 58 | |\