weifo

选择你所爱的,爱你所选择的


  • 首页

  • 存档

  • 分类

  • 标签

  • Search

ES6 - Map 和 Set

Posted on 2020-01-21 | In Javascript

Map 和 Set

JavaScript 的默认对象表示方式{}可以视为其他语言中的Map或Dictionary的数据结构,即一组键值对。

但是 JavaScript 的对象有个小问题,就是键必须是字符串。但实际上 Number 或者其他数据类型作为键也是非常合理的。

Map

Map是一组键值对的结构,具有极快的查找速度。

举个例子,假设要根据同学的名字查找对应的成绩,如果用Array实现,需要两个Array:

1
2
var names = ['Michael', 'Bob', 'Tracy']
var scores = [95, 75, 85]

给定一个名字,要查找对应的成绩,就先要在 names 中找到对应的位置,再从 scores 取出对应的成绩,Array 越长,耗时越长。

如果用 Map 实现,只需要一个“名字”-“成绩”的对照表,直接根据名字查找成绩,无论这个表有多大,查找速度都不会变慢。用 JavaScript 写一个 Map 如下:

Read more »

ES6 - generator

Posted on 2020-01-20 | In Javascript

基本概念

Generator 函数是 ES6 提供的一种异步编程解决方案。语法上,首先可以把它理解成,Generator 函数是一个状态机,封装了多个内部状态。

形式上,Generator 函数是一个普通函数,但是有两个特征。一是,function 关键字与函数名之间有一个星号;二是,函数体内部使用 yield 表达式,定义不同的内部状态。

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
// 该函数有三个状态:hello,world 和 return 语句(结束执行)
function* helloWorldGenerator() {
yield 'hello'
yield 'world'
return 'ending'
}

var hw = helloWorldGenerator()

// 只有调用 next() 函数才会执行

hw.next() // { value: 'hello', done: false }
hw.next() // { value: 'world', done: false }
hw.next() // { value: 'ending', done: true }
hw.next() // { value: undefined, done: true }

hw // {}

// yield表达式如果用在另一个表达式之中,必须放在圆括号里面
function* demo() {
console.log('Hello' + yield) // SyntaxError
console.log('Hello' + yield 123) // SyntaxError

console.log('Hello' + (yield)) // OK
console.log('Hello' + (yield 123)) // OK
}

Generator 函数的调用方法与普通函数一样,也是在函数名后面加上一对圆括号
不同的是,调用 Generator 函数后,该函数并不执行,返回的也不是函数运行结果,而是一个指向内部状态的指针对象

总结一下:

  • 调用 Generator 函数,返回一个遍历器对象,代表 Generator 函数的内部指针。
  • 以后,每次调用遍历器对象的 next 方法,就会返回一个有着 value 和 done 两个属性的对象。
    • value 属性表示当前的内部状态的值,是 yield 表达式后面那个表达式的值
    • done 属性是一个布尔值,表示是否遍历结束。

ES6 - Class

Posted on 2020-01-16 | In Javascript

简介

JavaScript 语言中,生成实例对象的传统方法是通过构造函数。下面是一个例子。

1
2
3
4
5
6
7
8
9
10
function Point(x, y) {
this.x = x
this.y = y
}

Point.prototype.toString = function() {
return '(' + this.x + ', ' + this.y + ')'
}

var p = new Point(1, 2)

ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类。

1
2
3
4
5
6
7
8
9
10
11
//定义类
class Point {
constructor(x, y) {
this.x = x // this 代表实例对象
this.y = y
}

toString() {
return '(' + this.x + ', ' + this.y + ')'
}
}
Read more »

ES6 - async await

Posted on 2020-01-12 | In Javascript

async 函数

async 函数是什么?一句话,它就是 Generator 函数的语法糖。async 函数就是将 Generator 函数的星号(*)替换成 async,将 yield 替换成 await,仅此而已

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function getSomething() {
return 'something'
}

async function testAsync() {
return 'Hello async'
}

async function test() {
const v1 = await getSomething() // 普通值
const v2 = await testAsync() // Promise对象
console.log(v1, v2)
}

test()
.then(() => {
console.log('调用该函数时,会立即返回一个Promise对象')
})
.catch(e => {})
Read more »

Vue 生命周期

Posted on 2020-01-06 | In Javascript

生命周期钩子函数

default

解释:

  • created阶段的ajax请求与mounted请求的区别:前者页面视图未出现,如果请求信息过多,页面会长时间处于白屏状态
  • mounted 不会承诺所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以用 vm.$nextTick

单个组件生命周期

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
 <template>
<div>
<h3>单组件</h3>
<el-button @click="dataVar += 1">更新 {{dataVar}}</el-button>
<el-button @click="handleDestroy">销毁</el-button>
</div>
</template>

<script>
export default {
data() {
return {
dataVar: 1
}
},
beforeCreate() {
this.compName = 'single'
console.log(`--${this.compName}--beforeCreate`)
},
created() {
console.log(`--${this.compName}--created`)
},
beforeMount() {
console.log(`--${this.compName}--beforeMount`)
},
mounted() {
console.log(`--${this.compName}--mounted`)
},
beforeUpdate() {
console.log(`--${this.compName}--beforeUpdate`)
},
updated() {
console.log(`--${this.compName}--updated`)
},
beforeDestroy() {
console.log(`--${this.compName}--beforeDestroy`)
},
destroyed() {
console.log(`--${this.compName}--destroyed`)
},
methods: {
handleDestroy() {
this.$destroy()
}
}
}
</script>

总结:

  • 初始化组件时,会执行beforeCreate/Created/beforeMount/mounted四个钩子函数
  • 当改变data中定义的变量(响应式变量)时,会执行beforeUpdate/updated钩子函数
  • 当切换组件(当前组件未缓存)时,会执行beforeDestory/destroyed钩子函数
  • 初始化和销毁时的生命钩子函数均只会执行一次,beforeUpdate/updated可多次执行

父子组件生命周期

Sequelize - 使用 model 查询数据

Posted on 2020-01-03 | In Sequelize

Sequelize 中有两种查询:使用 Model(模型)中的方法查询和使用 sequelize.query() 进行基于 SQL 语句的原始查询。

下面是事先创建好的数据:

1
2
3
4
5
6
7
8
9
10
11
12
mysql> select * from users;
+----+----------+------+------+-------+
| id | name | age | sex | score |
+----+----------+------+------+-------+
| 1 | guodada0 | 15 | 0 | 60 |
| 2 | guodada1 | 16 | 1 | 80 |
| 3 | guodada2 | 17 | 0 | 55 |
| 4 | guodada3 | 18 | 1 | 87 |
| 5 | guodada4 | 19 | 0 | 73 |
| 6 | guodada5 | 20 | 1 | 22 |
+----+----------+------+------+-------+
6 rows in set (0.00 sec)

findAll - 搜索数据库中的多个元素

1
2
3
4
5
6
const result = await UserModel.findAll() // result 将是所有 UserModel 实例的数组

// the same as
const result = await UserModel.all()

//...

限制字段

查询时,如果只需要查询模型的部分属性,可以在通过在查询选项中指定 attributes 实现。该选项是一个数组参数,在数组中指定要查询的属性即可,这些要查询的属性就表示要在数据库查询的字段:

1
2
3
Model.findAll({
attributes: ['foo', 'bar']
})

字段重命名

查询属性(字段)可以通过传入一个嵌套数据进行重命名:

1
2
3
4
5
Model.findAll({
attributes: ['foo', ['bar', 'baz']]
})

// SELECT foo, bar AS baz ...

demo

1
2
3
4
5
6
7
8
9
const results = await UserModel.findAll({
attributes: [['name', 'username'], 'age', 'score']
})

// [{"username":"guodada0","age":15,"score":60},{"username":"guodada1","age":16,"score":80} ...]
ctx.body = results

// 访问查询结果 通过 instance.get('xxx')
console.log(results[0]['username'], results[0].get('username')) // undefind, 'guodada0'

通过 sequelize.fn 方法进行聚合查询

base demo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const UserModel = sequelize.define('user', {
name: Sequelize.STRING,
age: Sequelize.INTEGER,
sex: Sequelize.INTEGER,
score: Sequelize.INTEGER
})

sequelize.sync().then(async () => {
try {
const results = await UserModel.findAll({
attributes: ['name', 'age', 'score']
})
results.map(user => {
console.log(user.name, user.age, user.score) // guodada0 15 60 | guodada1 16 80...
})
} catch (err) {
console.log(err)
}
})

// SELECT `name`, `age`, `score` FROM `users` AS `user`;

通过 sequelize.fn 方法进行聚合查询

1
2
3
Model.findAll({
attributes: [[sequelize.fn('COUNT', sequelize.col('hats')), 'no_hats']]
}) // SELECT COUNT(hats) AS no_hats ...

在使用聚合函数时,要给聚合字段指定一个别名。如,在上例中我们为聚合函数指定了别名'no_hats',这样我们就能在查询的回调函数实例中通过 instance.get('no_hats')来访问聚合统计的结果。

demo

1
2
3
4
5
const results = await UserModel.findAll({
attributes: [[sequelize.fn('SUM', sequelize.col('score')), 'scoreSum']]
})

console.log(results[0].get('scoreSum')) // 377

include/exclude

当需要查询所有字段并对某一字段使用聚合查询时,而只需要以对象的形式传入 attributes 并添加 include 子属性即可。

1
2
3
4
5
6
7
8
9
10
11
// 拽定全查询字段比较麻烦
Model.findAll({
attributes: ['id', 'foo', 'bar', 'baz', 'quz', [sequelize.fn('COUNT', sequelize.col('hats')), 'no_hats']]
})

// 这样会比较简短,且在你添加/删除属性后不会出错
Model.findAll({
attributes: { include: [[sequelize.fn('COUNT', sequelize.col('hats')), 'no_hats']] }
})

// SELECT id, foo, bar, baz, quz, COUNT(hats) AS no_hats ...

全部查询时,可以通过 exclude 子属性来排除不需要查询的字段:

1
2
3
4
5
Model.findAll({
attributes: { exclude: ['baz'] }
})

// SELECT id, foo, bar, quz ...

通过 sequelize.fn 方法进行聚合查询

随笔 - 如何用es6+写出优雅的js代码

Posted on 2019-12-12 | In 开发随笔

兼容 IE ?不存在的好吗。

其实使用新语法配合 babel 的转码,已经可以解决这一些问题了。既然如此,那就多使用新语法去探索一下怎么更好的去写代码吧。

下面分享个人开发中常用的 js 写法技巧,希望对各位有所帮助。

使用 let / const

var 命令会发生”变量提升“现象,即变量可以在声明之前使用,值为 undefined。这种现象多多少少是有些奇怪的。

个人认为,对声明的变量确定后面不会发生更改时,即使性能上没有太大提升差异在,但使用 const, 代码的可读性也会增强很多。

  • const 实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。
  • let 变量指向的内存地址,保存的只是一个指向实际数据的指针

补充 const 定义的变量不是数据不可变,而是保存的引用地址不能发生改变。例子如下:

1
2
3
4
const person = { age: 22 }
person.age = 1

console.log(person.age) // 1

详情看 let 和 const 命令

Read more »

五分钟了解(安装)typescript

Posted on 2019-11-14 | In 技术

typescript的由来

typescript是由微软的一个技术团队开发和维护的一个开源项目,之所以会推出这个项目是为了解决js的一个缺陷吧!由于Javascript是一种动态弱类型的语言,在测试和debug阶段会非常的痛苦,也是为了解决这一“痛点”,微软的VS code团队推出了typescript
  (强弱/动态静态具体解释,click here!)

安装

1
npm install -g typescript

安装后即可通过 tsc -v 命令行来查看安装版本,如果提示tsc不是内部或外部命令的话,说明系统的环境变量没有配置,csdn上有相关的解决办法。

编译

1
tsc xxx.ts

编译后会在相同文件夹下生成同名的js文件,关于更加工程化地使用typescript可以参考官方文档

变量和函数声明

与js语法相比,在所有的变量加上类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
let taylor:string='Taylor';
let age:number=25;

// 数组有两种定义方式
let skills:string[]=['sing','gituar','writing'];
let cats:Array<string>=['white','dog','miao'];


// 函数声明
function info(name:string,age:number):string{
let s:string='';
s=`He is ${name},and he's ${age} years old`;
return s;
}
info('calvin harris',28)

接口和类

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
// 可选属性
interface employee{
degree?:string,
skilled?:boolean
}
function test(config:employee):boolean{
if(config.skilled){
return true
}else if(config.degree==='master'){
return true
}else{
return false
}
}
let t1=test({degree:'master'})
let t2=test({degree:'bachelor',skilled:'false'})
let t3=test({skilled:'true'})
console.log(t1,t2,t3)

// 只读属性
interface Point{
readonly x:number,
readonly y:number
}
let p1:Point={x:10,y:5}
p1.y=12
// error

包学不会的深拷贝与浅拷贝

Posted on 2019-11-14 | In 前端开发

深拷贝与浅拷贝的含义

首先要知道在js的世界中,有两种类型的值,分别是基础类型和引用类型。基础类型包括string,number,boolean,Symbol,undefined,null,引用类型包括array,object等。

  • 基本数据类型:直接存储在栈(stack)中的数据
  • 引用数据类型:在栈中存放的是指针,真实的数据存放在堆中。

首先要分清拷贝和赋值的区别
引用类型的赋值是直接赋值了一个指针,二者指向相同的数据内存。而拷贝是要创建一个新的对象/数组,如果只拷贝一层数据的话叫浅拷贝,如果拷贝多层数据叫深拷贝。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
let obj={
name:'Mike',
age:36,
hobby:['movies','music','running']
}
// 这是赋值,任何一个都能操作共有的内存数据
let obj1=obj;
obj1.name='fred';
obj1.hobby[1]='eat';
console.log(obj,obj1);

// 这是浅拷贝,只能拷贝一层数据,当对象中有引用类型的value时,只会拷贝这个引用的指针
let obj2={...obj};
obj2.name='max';//不会改变源对象
obj2.hobby[1]='sleep'; //会改变源对象
console.log(obj,obj2)

如何实现浅拷贝

数组的浅拷贝

  • slice方法

    1
    2
    3
    4
    let arr=[1,5,9],
    arr1=arr.slice();
    arr1.push(11);
    console.log(arr,arr1)
  • concat方法,当不给concat传参时,该方法和slice()作用相同

    1
    2
    let arr1=arr.concat();
    ...
  • spread操作符

    1
    2
    3
    4
    5
    6
    let arr=[1,3,5,[8,9]];
    let arr1=[...arr];
    arr.push(15);
    console.log(arr,arr1);
    arr1[3].push(18);
    console.log(arr,arr1);

对象的浅拷贝

  • 手动实现

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    function shallowCopy(src){
    var target={};
    for(let key in src){
    if(src.hasOwnProperty(key)){
    target[key]=src[key];
    }
    }
    return target
    }
    // hasOwnProperty方法可以排除来自原型链上的属性
  • Object.assign()

    1
    2
    3
    4
    let obj={a:{name:'weifo',age:33}};
    let copyobj=Object.assign({},obj);
    copyobj.a.name='curt';
    concole.log(obj.a.name);//curt
  • spread

    1
    2
    3
    let obj={name:'weifo',skill:['english','code']};
    let copyobj={...obj,name:'fred'};//{name:'fred',skill:[...]}
    //es6语法

深拷贝的实现

  • trick版

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    JSON.parse(JSON.stringify(obj))
    // 该方法的局限性:symbol,undefined,函数的属性值会被忽略,例子如下
    let syb=Symbol(12);
    let obj={
    name:'fred',
    say:function(){
    alert('It wont alert');
    },
    syb:syb,
    age:undefined
    }
    let copy=JSON.parse(JSON.stringify(obj));
    console.log(copy);//{name:'fred'}
  • 手动实现

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    function deepclone(src){
    if(typeof src==='object'){
    let clone=Array.isArray(src)?[]:{};
    for(let key in src){
    clone[key]=deepclone(src[key]);
    }
    return clone
    }else{
    return src;
    }
    }
    let test={
    name:'fred',
    cities:['tokyo','paris','london']
    }
    let clone=deepclone(test);
    clone.cities.push('rome');
    clone.name='weifo';
    console.log(test,clone)
  • 解决循环引用
    上面的方法可以满足大部分的应用场景了,除了遇到对象引用自身的情况,如果采用上面的方法,会有爆栈的错误提示。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    const test={
    name:'weifo',
    field:[3,5,11],
    field1:{
    child:'name'
    }
    }
    test.test=test;//循环引用
    deepclone(test)//RangeError

为了解决循环引用的问题,我们可以额外开辟一个存储空间,来存储当前对象和拷贝对象的对应关系,当需要拷贝对象时,先去存储对象中找,找到的话直接返回,没有则继续拷贝。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function deepclone(target,map=new Map()){
if(typeof target==='object'){
let clone=Array.isArray(src)?[]:{};
if(map.get(target)){
return target
}
map.set(target,clone);
for(let key in target){
clone[key]=clone(target[key],map);
}
return clone
}else{
return target
}
}

  • 使用lodash
    1
    2
    3
    4
    5
    var _=require('lodash');
    var objects = [{ 'a': 1 }, { 'b': 2 }];
     
    var deep = _.cloneDeep(objects);
    console.log(deep[0] === objects[0]);//false

webpack-plugins

Posted on 2019-10-12 | In webpack

功能类

html-webpack-plugin

  • 把编译后的文件(css/js)插入到入口文件中,可以只指定某些文件插入,可以对 html 进行压缩等
  • filename:输出文件名;
  • template:模板文件,不局限于 html 后缀哦;
  • removeComments:移除 HTML 中的注释;
  • collapseWhitespace:删除空白符与换行符,整个文件会压成一行;
  • inlineSource:插入到 html 的 css、js 文件都要内联,即不是以 link、script 的形式引入;
  • inject:是否能注入内容到 输出 的页面去;
  • chunks:指定插入某些模块;
  • hash:每次会在插入的文件后面加上 hash ,用于处理缓存,如:;
    其他:favicon、meta、title ……;
Read more »

webpack - 理论篇

Posted on 2019-10-11 | In webpack

entry

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* @param {String} - String 时 打包为一个文件,默认包名 main.js
* @param {Array} - Array 时 webpack会把数组里所有文件打包成一个js文件
* @param {Object} - Object 时 webpack会把对象里的文件分别打包成多个文件
*
*/
module.exports = {
entry: './index.js',

entry: ['./index.js', './about.js'],

entry: {
app: './index.js',
about: './about.js'
},

entry: {
app: './index.js',
vendors: ['jquery'] // 分离第三方库
}
}
Read more »

webpack - 入门篇

Posted on 2019-10-10 | In webpack

什么是 webpack

webpack 可以看做是模块打包机:他做的事情是,分析你的项目结构,找到 JavaScript 模块以及其他的一些浏览器不能直接运行的扩展语言(Scss、TypeScript 等),将其打包为合适的格式以供浏览器使用

构建就是把源代码转换成发布到线上可执行的 JavaScript、CSS、HTML 代码,包括以下内容:

  • 代码转换:TypeScript 编译成 JavaScript、SCSS 编译成 CSS 等等
  • 文件优化:压缩 JavaScript、CSS、HTML 代码,压缩合并图片等
  • 代码分割:提取多个页面的公共代码、提取首屏不需要执行部分的代码让其异步加载
  • 模块合并:在采用模块化的项目有很多模块和文件,需要构建功能把模块分类合并成一个文件
  • 自动刷新:监听本地源代码的变化,自动构建,刷新浏览器
  • 代码校验:在代码被提交到仓库前需要检测代码是否符合规范,以及单元测试是否通过
  • 自动发布:更新完代码后,自动构建出线上发布代码并传输给发布系统。

构建其实是工程化、自动化思想在前端开发中的体现。把一系列流程用代码去实现,让代码自动化地执行这一系列复杂的流程。

Read more »

面试题积累

Posted on 2019-07-16 | In 开发随笔

Javascript

正则

  • 匹配整数
1
2
3
4
5
6
7
var str = '102'
// 1. ^(-|\+) 以 - 或者 + 开头
// 2. ? 表示出现或者不出现
// 3. [1-9] 取值范围,也是首字符的取值范围
// 4. \d*$ :* 等价于{0,},表示出现任意次,有可能不出现。
var reg = /^(-|\+)?[1-9]\d*$/
reg.test(str)
  • 用正则把[1,2,3,4]转换成 '1', '2', '3', '4'
Read more »

js - 笔试题收集

Posted on 2019-07-11 | In 开发随笔

提取 get 请求参数

有这样一个 URL:http://item.taobao.com/item.htm?a=1&b=2&c=&d=xxx&e,请写一段JS程序提取URL中的各个GET参数(参数名和参数个数不确定),将其按key-value形式返回到一个json结构中,如`{a:'1', b:’2’, c:’’, d:’xxx’, e:undefined}`。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
let str = 'http://item.taobao.com/item.html?a=1&b=2&c=&d=xxx&e&a=2'

function test(str) {
let params = {}
const paramsStr = str.replace(/.*\?/, '') // 提取参数字符串

// [ 'a=1', 'b=2', 'c=', 'd=xxx', 'e' ]
paramsStr.split('&').forEach(v => {
d = v.split('=') // [a, 1] [b, 2] [c, ''] [d, xxx] [e]
if (d[0] in params) {
Array.isArray(params[d[0]]) ? params[d[0]].push(d[1]) : (params[d[0]] = [params[d[0]], d[1]])
} else {
params[d[0]] = d[1]
}
})
return params
}

console.log(test(str)) // { a: [ '1', '2' ], b: '2', c: '', d: 'xxx', e: undefined }

数组降维

Read more »

页面重绘和回流以及优化

Posted on 2019-07-10 | In 开发随笔

重绘 redraw & 重排 reflow

浏览器运行机制图:
enter description here

浏览器的运行机制

1.构建DOM树(parse): 渲染引擎解析HTML文档,首先将标签转换成DOM树中的DOM node(包括js生成的标签)生成内容树(Content Tree/DOM Tree);
2.构建渲染树(construct):解析对应的CSS样式文件信息(包括js生成的样式和外部css文件),而这些文件信息以及HTML中可见的指令(如),构建渲染树(Rendering Tree/Frame Tree);
3.布局渲染树(reflow/layout):从根节点递归调用,计算每一个元素的大小、位置等,给出每个节点所应该在屏幕上出现的精确坐标;
4.绘制渲染树(paint/repaint):遍历渲染树,使用UI后端层来绘制每个节点。

Read more »

HTTP - TCP 三次握手四次挥手

Posted on 2018-11-21 | In HTTP

TCP 的三次握手

HTTP 请求与 TCP 链接之间的关系,在客户端向服务端请求和返回的过程中,是需要去创建一个 TCP connection,因为 HTTP 是不存在链接这样一个概念的,它只有请求和响应这样一个概念,请求和响应都是一个数据包,中间要通过一个传输通道,这个传输通道就是在 TCP 里面创建了一个从客户端发起和服务端接收的一个链接,TCP 链接在创建的时候是有一个三次握手(三次网络传输)这样一个消耗在的。

下面是 TCP 报文格式图:


↓↓↓↓

有几个字段需要重点介绍下:

  1. Seq 序号: sequeence number,用来标识从 TCP 源端向目的端发送的字节流,发起方发送数据时对此进行标记。
  2. 确认序号:acknowledgment number,只有 ACK 标志位为 1 时,确认序号字段才有效,Ack=Seq+1。
  3. 标志位:共 6 个,即 URG、ACK、PSH、RST、SYN、FIN 等,具体含义如下:
    • URG:紧急指针(urgent pointer)有效。
    • ACK:确认序号有效。
    • PSH:接收方应该尽快将这个报文交给应用层。
    • RST:重置连接。
    • SYN:发起一个新连接。
    • FIN:释放一个连接。
Read more »

webpack - babel篇

Posted on 2018-10-01 | In webpack

Babel 是一个让我们能够使用 ES 新特性的 JS 编译工具,我们可以在 webpack 中配置 Babel,以便使用 ES6、ES7 标准来编写 JS 代码。

本文以当前最新版本的 babel - 7.10 为例, 做 babel 的配置. 相关版本号如下

1
2
3
4
5
6
7
8
9
10
11
12
{
"devDependencies": {
"@babel/core": "^7.1.6",
"@babel/plugin-proposal-decorators": "^7.1.6",
"@babel/plugin-transform-runtime": "^7.1.0",
"@babel/preset-env": "^7.1.6",
"@babel/runtime": "^7.1.5",
"babel-loader": "^8.0.4",
"webpack": "^4.26.1",
"webpack-cli": "^3.1.2"
}
}
Read more »
12
weifo

weifo

行到水穷处,坐看云起时

37 posts
17 categories
19 tags
RSS
GitHub
© 2025 weifo
Powered by Hexo
|
Theme — NexT.Gemini v5.1.4