shell 基础

一直以来在 Linux 环境下都是用 Python 来写脚本,但很多时候使用 Shell 脚本 更方便一点,之前也都是现查现用,比较麻烦而且耗时,所以学习并记录下来方便之后的查阅。

简单的脚本程序

1
2
#!/bin/bash
echo "Hello Shell World!"

以上就是一个 Shell 脚本,第一行#!/bin/bash告诉系统脚本使用那个解释器来执行,之后只要添加执行权限就可以运行了

1
2
chmod +x xxx.sh
./xxx.sh
阅读更多
javascript 有限状态机

有限状态机是一种模型,模拟事物状态的变化,有以下特点

  • 可以用状态来描述事物,并任意时刻事物总是处于一种状态
  • 事物拥有的状态是有限个的
  • 某种条件下,状态可以发生改变,变为另一种状态

以下是阮一峰老师在博客中写的例子JavaScript 与有限状态机

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var menu = {
// 当前状态
currentState: 'hide', // 绑定事件
initialize: function() {
var self = this
self.on('hover', self.transition)
}, // 状态转换
transition: function(event) {
switch (this.currentState) {
case 'hide':
this.currentState = 'show'
doSomething()
break
case 'show':
this.currentState = 'hide'
doSomething()
break
default:
console.log('Invalid State!')
break
}
}
}

这个例子展示的是 menu 触发 hover 时改变 menu 的显示状态。

阅读更多
javascript 函数防抖和函数节流

昨天在逛掘金的时候无意间看到 Js 防抖和节流的主题, 什么东西听都没听过,看了以后才明白是特别实用的东西,所以记录一下。

作者:薄荷前端
链接:7 分钟理解 JS 的节流、防抖及使用场景
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
Git 地址 https://github.com/BooheeFE/weekly/issues/13

函数防抖

在事件被触发 n 秒后再执行回调,如果在这 n 秒内又被触发,则重新计时。

1
2
3
4
5
6
7
8
9
function ajax(content) {
console.log('ajax request ' + content)
}

var inputa = document.getElementById('unDebounce')

inputa.addEventListener('keyup', function(e) {
ajax(e.target.value)
})

这个例子中每次键盘输入都会触发一次 ajax 请求, 用户查询内容的时候会发送多次不必要的查询。可以通过防抖来过滤不必要的请求

阅读更多
javascript 观察者模式和发布订阅模式

通过例子理解观察者模式和发布订阅模式的区别

观察者模式

Subject 是一个主题,Observer 是一个观察者。观察者可以订阅主题,主题发生变化会通知观察者。这是一个典型的观察者模式

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
class Subject {
constructor() {
// 订阅主题的观察者, subscriber
this.subs = []
}

subscribe(sub) {
// 订阅
this.subs.push(sub)
}

unsubscribe(sub) {
// 取消订阅
const index = this.subs.indexOf(sub)
if (index > -1) {
this.subs.splice(index, 1)
}
}

fire() {
// 主题变化,通知订阅主题的观察者
this.subs.forEach(sub => {
sub.notify()
})
}
}

class Observer {
constructor(data) {
this.data = data
}

notify() {
console.log(this.data)
}
}

let subject = new Subject()
let ob1 = new Observer('hello')
let ob2 = new Observer('world')
subject.subscribe(ob1)
subject.subscribe(ob2)
subject.fire()
阅读更多
javascript 事件机制

当我们对一个元素和他的子元素各绑定事件时候,点击元素会触发两个事件

1
2
3
<div class="box1">
<div class="box2"></div>
</box>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
box1.addEventListener(
'click',
function(e) {
console.log('click box1')
},
false
)

box2.addEventListener(
'click',
function(e) {
console.log('click box2')
},
flase
)

可以看到先触发 box2 在触发 box1, 如果想要阻止 box1 事件,添加stopPropagation阻止事件传递

1
2
3
4
5
6
7
8
box2.addEventListener(
'click',
function(e) {
e.stopPropagation()
console.log('click box2')
},
flase
)

这样就只执行了 box2 事件,相反也可以阻止 box2 事件只执行 box1

阅读更多
栈的括号匹配

栈是一种后进先出的队列(LIFO), 是一种存储数据的容器.

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
class Stack {
constructor() {
this.list = []
}

getSize() {
return this.list.length
}

isEmpty() {
return this.getSize() === 0
}

push(e) {
this.list.push(e)
}

pop() {
return this.list.pop()
}

top() {
if (this.getSize() === 0) {
return null
}
return this.list[this.getSize() - 1]
}
}
;(function main() {
let list = new Stack()
list.push(3)
list.push(5)
list.push(1)
console.log(`栈顶元素为: ${list.top()}`)
list.pop()
console.log(`栈顶元素为: ${list.top()}`)
})()
阅读更多
字符串匹配

朴素匹配算法

朴素匹配算法是对目标字符串和模板字符串的一一匹配。如果匹配得上,下标向右移一位, 否则清空并重新开始匹配。

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
const match = (target, pattern) => {
let [i, j] = [0, 0]
let [n, m] = [target.length, pattern.length]
while (i < n && j < m) {
if (target[i] == pattern[j]) {
console.log(
`匹配的元素: target[${i}]=${target[i]}, pattern[${j}]=${pattern[j]}`
)
i += 1
j += 1
} else {
console.log(
`不匹配的元素: target[${i}]=${target[i]}, pattern[${j}]=${pattern[j]}`
)
i = i - j + 1
j = 0
}
}
if (j == m) {
return i - j
}
return -1
}
;(function main() {
let target = 'abb abad abac'
let pattern = 'abac'
console.log('target', target)
console.log('pattern', pattern)
match(target, pattern)
})()
阅读更多
链表

单链表

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
80
class Node {
constructor(data, next = null) {
this.data = data
this.next = next
}
}

class List {
constructor() {
// 初始化
this.head = null
this.length = 0
}

isEmpty() {
return this.length == 0
}

getSize() {
return this.length
}

append(e) {
/*
从head开始以为循环到尾部, 追加新的节点
如果创建pop函数也是一样
*/
if (this.head === null) {
this.head = new Node(e)
this.length += 1
} else {
let head = this.head
while (head.next !== null) {
head = head.next
}
head.next = new Node(e)
this.length += 1
}
}

reverse() {
/*
反转链表
移动head指针,指向下个节点, 并把原来节点指向上一个节点
*/
let p = null
let head = this.head
while (head !== null) {
// 把head赋值给q, 这里q和head都指向同一个Node
let q = head
// 然后head指向给了下一个节点
head = q.next
// q指向上一个节点
q.next = p
// 把当前节点指向为上一个节点
p = q
}
this.head = p
}

print() {
let idx = 0
let head = this.head
while (head !== null) {
idx += 1
console.log(`idx ${idx}, data: ${head.data}`)
head = head.next
}
}
}

;(function main() {
let list = new List()
list.append(3)
list.append(5)
list.append(1)
list.print()
list.reverse()
list.print()
})()
阅读更多
javascript 继承

继承是面向对象中的重要部分,像 java、python 等语言都是用类来继承的,而 js 的继承是通过原型链来实现的。

原型链

通过将 prototype 指向对象的实例,来实现继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function SuperType() {
this.property = true
}

SuperType.prototype.getSuperValue = function() {
return this.property
}

function SubType() {
this.subproperty = false
}

// 继承 SuperType
SubType.prototype = new SuperType()

SubType.prototype.getSubValue = function() {
return this.subproperty
}

var instance = new SubType()
console.log(instance.getSuperValue()) // true
阅读更多
css float 浮动

在网页布局中除了 position 属性以外最常用的就是 float 属性,使用 float 属性的元素会脱离标准文档流,并根据 float 属性进行左右浮动。

使用 float 属性

多个 div 元素根据文档流会呈现层级结构

当我们给 yellow 设置浮动属性以后,就脱离了文档流 red 填充原有 yellow 所占的位置

阅读更多