palmerye / knowledge-network Goto Github PK
View Code? Open in Web Editor NEWKnowledge-Network
Knowledge-Network
一般用过电脑的人,都对Excel不陌生。Excel是一张二维表格,通过行列来记录和描述数据。简单来说,类比在数据库中,也是一张张表,区别在于,数据库中的多张表是可以相互联系的。所以粗暴地理解数据库,就是多张表+各表之间的关系
。
所以我们学习的方向可以这样:
闭包使得函数可以继续访问定义时的词法作用域。
保持对函数定义时的词法作用域的引用,这个引用就是闭包。
像轮子哥说的,什么是闭包? - 知乎用户的回答 - 知乎,闭包就是封闭外部状态,而不是封闭内部状态。即函数定义时外部的词法作用域失效时(js引擎的垃圾回收器考虑回收它),但由于这个词法作用域被内部其他函数引用,无法被回收,所以这个外部状态就被保留了下来,这就是所谓的封闭外部状态。
闭包就是一个引用,该函数在定义时的词法作用域scope以外执行时,因为有了这个引用(闭包),使得该函数能继续访问定义时的词法作用域scope。
function foo() {
var a = 2
function bar() {
console.log(a);
}
return bar
}
var cat = foo()
cat() // 2
看这个栗子:
for (var i = 1; i <= 5; i++) {
setTimeout(function timer() {
console.log(i)
}, i*100);
}
// result: 6 6 6 6 6
看这段代码的语义,是想输出1 2 3 4 5
,实际则不然。这里的 i 都被封闭在外部(全局作用域)中,因此只有一个 i 。由于定时器回调函数式在循环结束后执行,这时i为6,因此回调函数中输出的是i=6.因此要解决这个问题,我们必须在每一次循环迭代中有自己的作用域。我们做以下尝试:
for (var i = 1; i <= 5; i++) {
(function () { // 这里用了一个IIFE,在每次迭代中创建封闭的作用域
setTimeout(function timer() {
console.log(i)
}, i*100);
})()
}
// result: 6 6 6 6 6
但为什么还是存在问题呢,因为这个封闭的作用域中,仍旧是循环结束后执行(i=6),该作用域中的i并没有被封闭起来。那我们再改造下,把封闭作用域中的i存起来。
for (var i = 1; i <= 5; i++) {
(function (i) {
setTimeout(function timer() {
console.log(i)
}, i*100);
})(i)
}
// result: 1 2 3 4 5
px pt em rem vh vw
的区别px
:像素,与显示设备有关,通常是一个设备像素点pt
:磅,1 pt = (1 / 72) in, 1 in = 96 px,3 pt = 4 px
em
:1em
等于元素的父元素的字体大小,假设设置 body { font-size: 20px; }
,那么1em = 20px
rem ( root em )
:CSS3 单位,只是相对 HTML
根元素,假设设置 html{ font-size: 10px; }
,那么1rem = 10px
单位 | 解释 |
---|---|
vw | 1vw = 视口宽度的1% |
vh | 1vh = 视口高度的1% |
vmin | 选取vw和vh中最小的那个 |
vmax | 选取vw和vh中最大的那个 |
Block formatting context直译为"块级格式化上下文",BFC是一个容器,用于管理块级元素。
linear-gradient
background: linear-gradient(direction, color-stop1, color-stop2, ...);
值 | 描述 |
---|---|
direction | 用角度值指定渐变的方向(或角度)。 |
color-stop1, color-stop2,... | 用于指定渐变的起止颜色。 |
function f1(callback) {
setTimeout(function () {
console.log('f1')
callback()
}, 1000)
}
function f2() {
console.log('f2')
}
f1(f2)
el 和 data 并未初始化
完成了 data 数据的初始化,el 不可见
完成了 el 和 data 初始化
完成挂载
数据改变——导致虚拟DOM的改变——调用这两个生命钩子去改变视图,这个数据只有和模版中的数据绑定了才会发生更新。
在beferoDestory生命钩子调用之前,所有实例都可以用,但是当调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
let vm = new Vue({
el: '#app',
data: {
message: 1
},
template: '<div id="app"><p>{{message}}</p></div>',
beforeCreate() {
console.log('调用了beforeCreate')
console.log(this.message)
console.log(this.$el)
},
created() {
console.log('调用了created')
console.log(this.message)
console.log(this.$el)
},
beforeMount() {
console.log('调用了beforeMount')
console.log(this.message)
console.log(this.$el)
},
mounted() {
console.log('调用了mounted')
console.log(this.message)
console.log(this.$el)
},
beforeUpdate() {
console.log('调用了beforeUpdate')
console.log(this.message)
console.log(this.$el)
},
updated() {
console.log('调用了updated')
console.log(this.message)
console.log(this.$el)
},
beforeDestory() {
console.log('调用了beforeDestory')
console.log(this.message)
console.log(this.$el)
},
destoryed() {
console.log('调用了Destoryed')
console.log(this.message)
console.log(this.$el)
}
})
vm.message = 2
// 调用了beforeCreate
// undefined
// undefined
// 调用了created
// 1
// undefined
// 调用了beforeMount
// 1
// <div></div>
// 调用了mounted
// 1
// <div id="app"><p>1</p></div>
// 调用了beforeUpdate
// 2
// <div id="app"><p>2</p></div>
// 调用了updated
// 2
// <div id="app"><p>2</p></div>
props
Vue.component('child', {
props: ['title'],
template: '<h3>{{ title }}</h3>'
})
// parent component
<child title="My journey with Vue"></child>
$emit
2015 年,Sam Newman 提出了 Pattern: Backends For Frontends,为了适应体验者API(高频变更)。其中原则之一是服务自治,谁使用谁开发,即它应该由前端同学去维护。
远程过程调用
数据密集型实时持程序
其关键点是要将应用程序的IO操作分为两个步骤来理解:IO调用(由进程发起)和IO执行。IO调用才是应用程序干的事情,而IO执行是操作系统的工作。
在IO调用时,对待操作系统IO就绪状态的不同方式,决定了其是阻塞或非阻塞模式;在IO执行时,线程或进程是否挂起等待IO执行决定了其是否为同步或异步IO。
先来从最简单的场景来看为什么要有
Redis
缓存这个东西。
cache-control
,但在缓存时间内,用户可能得到旧数据。×Radis
就这样来了。√Radis
服务不能说崩就崩啊,一旦崩了,缓存(放在内存里)不就没了么,所以要保证这台服务器的持久性,所以这里的持久化指的是,把缓存放在硬盘里,这样重启后依然能用是功能一次的缓存。CAS(Central Authentication Service)是耶鲁大学的一个开源项目,旨在为web应用系统提供一种可靠的单点登录(SSO)解决方案。
顾名思义,单例就是单个实例,一个类只有一个实例。即使多次实例化该类,也只返回第一次实例化后的实例对象,能减少不必要的内存开销, 并且也能减少全局的函数和变量冲突。
VisuAlgo:通过动画学习算法和数据结构。VisuAlgo 源自 Steven Halim 博士的一个工具,用于帮助他的学生更好理解学习数据结构和算法。
https://visualgo.net/zh
MVC的其中一个缺点便是没有明确的定义,所以不同的实现(比如Struts和ASP.NET MVC)细节上都是不一样的。MVC一般的流程是这样的:View(界面)触发事件 --> Controller(业务)处理业务,触发了数据更新 --> 更新Model的数据 --> Model(带着数据)回到了View --> View更新数据
在经典MVC中,controller是用户和系统之间的链接;但在现代的UI系统中,其中controller的功能已经意义不大了。
可见,MVP和MVC的依赖关系图应该是一样的,Model-View-Presenter是在MVC的基础上,进一步规定了Controller中的一些概念而成的,所以presenter它就是一种controller。
MVVM中最重要的概念是数据绑定,用双向绑定的方式替代了MVC和MVP中的view和model的互相通讯,这进一步把逻辑代码变成了声明模式。
参考:
Winter大大写的文章:《谈谈UI架构设计的演化》
你对MVC、MVP、MVVM 三种组合模式分别有什么样的理解? - Indream Luo的回答 - 知乎
一句话总结在前,在 JavaScript 中,
this
永远指向最后调用它的那个对象。
在js红皮书中关于this
的说法是,this对象是在运行时基于函数的执行环境绑定的。说的很明确,运行时、函数的执行环境,那我们先来看看这些是个啥。
git merge dev --squash
git commit -m "xxx"
在JavaScript中有5种基本数据类型,分别是
Undefined、Null、Boolean、Number、String
,还有一种复杂数据类型Object
,对象实质上就是属性的集合。在JavaScript中不能直接访问内存中的位置,因此JavaScript在操作对象时,实际上是在操作对象的引用。所以之所以字符串string
这个基本数据类型,有substring()
等对象方法,是因为JavaScript在读取基本数据值的时候,会创建一个对应的基本包装类型对象,这个对象上有一些扩展方法。
charAt(n)
返回第n个字符charCodeAt(n)
返回第n个字符编码concat()
拼接字符串
oldValue.concat('new value')
slice(x, y)
x代表起始位置,y代表终止位置(若空则默认返回最后位置),并返回子字符串
value.slice(1, 5)
substring(x, y)
同上substr(x, y)
y代表返回字符个数trim()
去除value前后空格后返回trimLeft()
删除前面的空格trimRight()
删除后面的空格toLowerCase()
转化为小写toUpperCase()
转化为大写indexOf(a, x)
在value
中搜索a,起始搜索位置为x,然后向后搜索,返回第一个结果下标lastIndexOf(a, x)
在value
中搜索a,起始搜索位置为x,然后向前搜索,返回第一个结果下标match()
只接收一个参数,正则表达式或者是RegExp对象localeCompare()
value.localeCompare(tovalue)
比较value和tovalue的字符串大小,若value排在tovalue前,则返回-1,否则返回1,相等返回0Doctype
作用Doctype
声明告诉浏览器应该按照什么规则集解析文档,其中,DTD
叫文档类型定义,里面包含了文档的规则,浏览器就根据你定义的 DTD
来解释你页面的标识。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
// xhtml1-transitional.dtd 属于 transitional 过渡的,还有,严格的(Strict),框架的(Frameset)
HTML5 只需要 <!DOCTYPE HTML>
,因为 HTML5
不基于 SGML
,而 HTML4.01
基于SGML
,所以需要引用DTD
a b i span img input select strong textarea
div ul ol li dl dt dd h1 h2 h3 h4…p section table
<br> <hr> <img> <input> <link> <meta>
width、height、margin-top、margin-bottom、padding-top、padding-bottom
无效。遇到defer脚本立即下载,但不立即执行,整个页面解析完成后运行,按出现的先后顺序执行,但实际不一定在DOMContentLoaded事件触发前执行
与defer脚本类似,但不能保证其顺序;且,async脚本一定会在load事件前执
// html,这里要注意,canvas的宽高要在节点上设置,默认值为300和150,单位为px,若在css中设置,则会使坐标系拉伸
<canvas id="demo" width="100" height="100"></canvas>
const CANVAS = document.getElementById('demo')
const ctx= CANVAS.getContext('2d') // 也可以是3d环境,则调用 WebGL, getContext('webgl')
canvas
2d坐标系是以左上角为原点,x向右y向下递增
// 绘制一个填充的矩形
fillRect(x, y, width, height)
// 绘制一个矩形的边框
strokeRect(x, y, width, height)
// 清除指定的矩形区域,然后这块区域会变的完全透明
clearRect(x, y, widh, height)
canvas
只支持一种原生的图形绘制:矩形。所有其他图形都至少需要生成一种路径path
ctx.beginPath() // 新建一条path
ctx.moveTo(50, 50) // 把画笔移动到指定的坐标
ctx.lineTo(70, 50) // 绘制一条从当前位置到指定坐标(200, 50)的直线.
ctx.closePath()
ctx.stroke() // 绘制路径
ctx.setLineDash([5,15])
绘制虚线,括号里的数组为虚线间隔
同理可得,多次
lineTo(x, y)
可以绘制各式各样的路径形状
ctx.beginPath() // 新建一条path
ctx.moveTo(50, 50) // 把画笔移动到指定的坐标
ctx.lineTo(70, 50) // 绘制一条从当前位置到指定坐标(70, 50)的直线.
ctx.lineTo(70, 90) // 绘制一条从当前位置到指定坐标(70, 90)的直线.
ctx.closePath()
ctx.stroke() // 绘制路径,填充则为 ctx.fill()
arc(x, y, r, startAngle, endAngle, anticlockwise)
arcTo(x1, y1, x2, y2, radius)
ctx.beginPath() // 新建一条path
ctx.arc(50, 50, 40, 0, Math.PI / 2, false)
ctx.stroke() // 绘制路径,填充则为 ctx.fill()
save()
和restore()
save()
保存当前Canvas画布状态并放在栈的最上面,可以使用restore()
方法依次取出。
绘图效果本身不会被保存,保存的只是绘图状态,包括:
transform()
clip()
setLineDash()
strokeStyle,fillStyle,globalAlpha,lineWidth,lineCap,lineJoin,miterLimit,lineDashOffset,shadowOffsetX,shadowOffsetY,shadowBlur,shadowColor,globalCompositeOperation,font,textAlign,textBaseline
1px线条模糊问题
曲线折线锯齿现象
handleResize (fn, delay = 0) {
let timer = null
return () => {
clearTimeout(timer)
timer = setTimeout(() => {
fn()
}, delay)
}
}
handleResize (fn, delay = 0, atleast = 0) {
let timer = null
let previous = null
return () => {
let now = +new Date()
if (!previous) {
previous = now
}
if (now - previous > atleast) {
fn()
previous = now
} else {
clearTimeout(timer)
timer = setTimeout(() => {
fn()
}, delay)
}
}
}
Array
构造函数
var array = new Array()
[]
数组字面量
var array = []
instanceof
if(value instanceof Array) ...
isArray
if(Array.isArray(value)) ...
toLocaleString()
toLocaleString()
方法toString()
toString()
方法valueOf()
join()
join()
传递的符号,可以得到以该符号分隔的字符串push()
pop()
unshift()
shift()
reverse()
sort()
toString()
方法,然后比较字符串大小(转成ASCII码)function compare(v1, v2) { v1比v2小返回负数, v1比v2大返回正数,相等返回0 } values.sort(compare)
contat()
先创建当前数组的一个副本,然后将接收到的一个或多个数组push
到当前数组,然后返回新数组。
splice()
value.splice(0, 2)
可删除前两项value.splice(1, 0,'item1', 'item2')
可在第一项后插入两项,返回新数组value.splice(2, 1,'item1', 'item2')
可删除当前数组位置2的项,再从位置2插入后两项,返回新数组indexOf()
lastIndexOf()
every()
true
some()
true
filter()
map()
forEach()
for
循环reduce()
value.reduce(function(prev, cur, index, array){return prev + cur})
可执行数组所有值求和,第一次迭代发生在数组的第二项,因此prev 为第一项,cur 为第二项
reduceRight()
Client和Server发起均可断开连接请求,以Client为例
为什么连接的时候是三次握手,关闭的时候却是四次握手?
简单的说,原因是TCP是全双工的,每个方向都必须要单独进行关闭。主动方发起断开请求,被动方收到断开请求时,回应ACK,等待数据传输完,再回应FIN。所以是多了等待前回应的这一次。
HTTPS经由HTTP进行通信,利用SSL/TLS来加密数据包,具有非对称加密的可靠性和对称加密的高效性
在浏览器运行非法的HTML标签或者JavaScript,是一种攻击者利用预先设置的陷阱触发的被动攻击
防御:设置 httpOnly;字段过滤;
一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法
防御:
代理其实就是在client端和真正的server端之前增加一层提供特定服务的服务器,即代理服务器proxy
客户端和代理服务器可以直接互相访问,属于一个LAN(局域网);代理对用户是非透明的,即用户需要自己操作或者感知得到自己的请求被发送到代理服务器;代理服务器通过代理用户端的请求来向域外服务器请求响应内容。
代理服务器和真正server服务器可以直接互相访问,属于一个LAN(服务器内网);代理对用户是透明的,即无感知。一般用于安全及权限和负载均衡。
正向代理是代理客户端,为客户端收发请求,使真实客户端对服务器不可见;而反向代理是代理服务器端,为服务器收发请求,使真实服务器对客户端不可见。
当用户在浏览器输入一串url地址,先从本地DNS服务器找缓存,若没有,则用递归或者迭代查询的方式向根域名服务器、顶级域名服务器、权威域名服务器查询IP地址,返回给浏览器
若遇到JS外链,由于JS可能会造成回流和重绘,因此会阻塞DOM树构建
无论是DOM还是CSSOM,都是要经过Bytes → characters → tokens → nodes → object model这个过程。
浏览器端的跨域问题,来源于它的安全策略:同源政策 same-origin policy。
同源指的是:
解决跨域问题:
两个网页一级域名相同,二级域名不同时,设置document.domain,且仅适用于 Cookie 和 iframe 窗口
浏览器内核又可以分成两部分:渲染引擎(layout engineer 或者 Rendering Engine)和 JS 引擎。它负责取得网页的内容(HTML、XML、图像等等)、整理讯息(例如加入 CSS 等),以及计算网页的显示方式,然后会输出至显示器或打印机。JS 引擎则是解析 Javascript 语言,执行 javascript 语言来实现网页的动态效果。最开始渲染引擎和 JS 引擎并没有区分的很明确,后来 JS 引擎越来越独立,内核就倾向于只指渲染引擎。
相同点
不同点
iframe
元素,他们的 sessionStorage是可以共用的。每次HTTP请求的时候,客户端都会发送相应的Cookie信息到服务端。实际上大多数的应用都是用 Cookie 来实现Session跟踪的,第一次创建Session的时候,服务端会在HTTP协议中告诉客户端,需要在 Cookie 里面记录一个Session ID,以后每次请求把这个会话ID发送到服务器,服务器就知道该用户的身份了。
浏览器是多进程的,新开一个tab页,基本上浏览器会新起一个进程(不排除有优化合并多个进程的可能)
负责渲染浏览器界面,解析HTML,CSS,构建DOM树和RenderObject树,布局和绘制等,重绘和回流时会触发这个线程。重要的是,GUI线程和JS引擎线程互斥,当JS引擎执行时GUI线程会被挂起,GUI更新会被保存在一个队列中等到JS引擎空闲时立即被执行
负责处理Javascript脚本程序
归属于浏览器而不是JS引擎,事件循环机制就是基于这个线程
setInterval与setTimeout所在线程,浏览器定时计数器并不是由JavaScript引擎计数的,计时完毕后,添加到事件队列中,等待JS引擎空闲后执行。W3C在HTML标准中规定,规定要求setTimeout中低于4ms的时间间隔算为4ms。
JS分为同步任务和异步任务,同步任务都在主线程上执行,形成一个执行栈,主线程之外,事件触发线程管理着一个任务队列,只要异步任务有了运行结果,就在任务队列之中放置一个事件。一旦执行栈中的所有同步任务执行完毕(此时JS引擎空闲),系统就会读取任务队列,将可运行的异步任务添加到可执行栈中,开始执行。
进一步,JS中分为两种任务类型:macrotask和microtask,在ECMAScript中,microtask称为jobs,macrotask可称为task
JavaScript 不是一门模块化的语言,没有类的概念,至于为什么模块化,多人协作,代码复用性,可测试性,...
Node端的模块化规范,CommonJs用同步的方式加载模块。在服务端,模块文件都存在本地磁盘,读取非常快,所以这样做不会有问题。但是在浏览器端,限于网络原因,更合理的方案是使用异步加载。
主要有module、exports、require、global 四个环境变量
// 用require加载模块,用module.exports定义当前模块对外输出的接口
// 尽量不要用exports直接导出
// math.js
var basicNum = 0;
function add(a, b) {
return a + b;
}
module.exports = {
add: add,
basicNum: basicNum
}
// main.js 加载math.js 模块
var math = require('./math');
math.add(1, 2);
Asynchronous Module Definition,目前,主要有两个Javascript库实现了AMD规范:require.js 和 curl.js。
// 用require.config()指定引用路径等,用define()定义模块,用require()加载模块
// 定义math.js模块
define(function () {
var basicNum = 0;
var add = function (x, y) {
return x + y;
};
return {
add: add,
basicNum :basicNum
};
});
// 异步加载
require(['math'], function(math){
var sum = math.add(1, 2);
});
此规范其实是在sea.js推广过程中产生的。AMD 推崇依赖前置、提前执行,CMD推崇依赖就近、延迟执行
// 定义模块 math.js
define(function(require, exports, module) {
var add = function(a,b){
return a+b;
}
exports.add = add;
});
// 加载模块
seajs.use(['math.js'], function(math) {
var sum = math.add(1, 2);
});
// AMD 推崇依赖前置、提前执行
define(["a", "b", "c", "d", "e", "f"], function(a, b, c, d, e, f) {
// 等于在最前面声明并初始化了要用到的所有模块
if (false) {
// 即便没用到某个模块 b,但 b 还是提前执行了
b.foo()
}
});
之前的几种模块化方案都是前端社区自己实现的,只是得到了大家的认可和广泛使用,而ES6的模块化方案是真正的规范。ES6 模块的功能主要由 export 和 import 组成。每一个模块都有自己单独的作用域,模块之间的相互调用关系是通过 export 来规定模块对外暴露的接口,
// 定义模块 math.js
var basicNum = 0;
var add = function (a, b) {
return a + b;
};
export { basicNum, add };
// 引入模块
import { basicNum, add } from './math';
// 使用import命令的时候,用户需要知道所要加载的变量名或函数名。其实ES6还提供了export default命令,为模块指定默认输出,对应的import语句不需要使用大括号
// 多种形态
import fs from 'fs'
import {default as fs} from 'fs'
import * as fs from 'fs'
import {readFile} from 'fs'
import {readFile as read} from 'fs'
import fs, {readFile} from 'fs'
export default fs
export const fs
export function readFile
export {readFile, read}
export * from 'fs'
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.