防抖和节流

防抖(debounce)

setTimeout 方法

1
2
3
4
5
6
7
8
9
10
11
var debounce = function(fn, delayTime) {
var timeId; // 用于存储定时器
// 闭包 防止 timeId 被销毁
return function() {
var context = this, args = arguments; // args 存储传入的参数
timeId && clearTimeout(timeout); // 判断定时器是否存在,存在则删除定时器
timeId = setTimeout(function{ // 添加定时任务
fn.apply(context, args);
}, delayTime)
}
}

思路解析:
执行 debounce 函数之后会返回一个新的函数,通过闭包的形式,维护一个变量 timeId ,每次执行该函数的时候会结束之前的延迟操作,重新执行 setTimeout 方法,也就实现了上面所说的指定的时间内多次触发同一个事件,会合并执行一次。

温馨提示:
  1. 上述代码中arguments只会保存事件回调函数中的参数,譬如:事件对象等,并不会保存 fn、delayTime
  2. 使用 apply 改变传入的fn方法中的this指向,指向绑定事件的 DOM 元素。
阅读更多

GitHub 问题汇总

关于我 hexo 博客上传问题

问题:Failed to connect to github.com port 443: Timed out
  1. ping github.com

    ping 不通看自己是不是启用了代理或vpn,然后再看 host 文件中 github 对应的地址是否能访问通。
    之前访问不通,在 host 文件中添加了

  2. 30.253.112 github.com

  3. 199.108.153 assets-cdn.github.com

  4. 199.109.153 assets-cdn.github.com

  5. 199.110.153 assets-cdn.github.com

  6. 199.111.153 assets-cdn.github.com

  7. 232.5.194 github.global.ssl.fastly.net

  8. 101.113.194 github.global.ssl.fastly.net
    我全部删除掉,怎么添加 host 我在 GitHub 技巧 有提到过。


相关资料
Failed to connect to github.com port 443: Timed out(Windows)
GitHub解决git@github.com: Permission denied (publickey).问题

WebSocket 从入门到实战开发

socket 官网的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io();

var form = document.getElementById('form');
var input = document.getElementById('input');

form.addEventListener('submit', function(e) {
e.preventDefault();
if (input.value) {
// 发送消息
socket.emit('chat message', input.value);
input.value = '';
}
});
// 接受消息
socket.on('chat message', function(msg) {
var item = document.createElement('li');
item.textContent = msg;
messages.appendChild(item);
window.scrollTo(0, document.body.scrollHeight);
});
</script>
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
const app = require('express')();
const http = require('http').Server(app);
const io = require('socket.io')(http);

app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html');
});

io.on('connection', (socket) => {
console.log('a user connected');
socket.on('disconnect', () => {
console.log('user disconnected');
});
// 接受消息
socket.on('chat message', (msg) => {
console.log('message: ' + msg);
});
// 广播 服务器端发送消息
socket.broadcast.emit('hi');
socket.emit('hi');

// 一对一
socket.to(id).emit('chat message', input.value);

// 断开连接
socket.on('disconnecting',function(){
});
});

http.listen(3000, () => {
console.log('listening on *:3000');
});

客户端

socket.io-client


相关资料
手摸手教你使用WebSocket
你不知道的WebSocket
零距离接触websocket
socketio

5000字!带你零距离接触websocket!

Chrome 调试

alert

console

基本输出

1
2
3
4
5
6
console.log("打印字符串");   // 在控制台打印字符串
console.error("我是个错误"); // 在控制台打印错误信息
console.info("我是个信息"); // 在控制台打印信息
console.warn("我是个警告"); // 在控制台打印警告信息
console.debug("我是个调试"); // 在控制台打印调试信息
console.clear(); // 清空控制台

格式化输出

1
2
3
4
5
6
console.log("%s年",2016);         // %s表示字符串
console.log("%d年%d月",2016,11); // %d表示整数
console.log("%f",3.1415926); //%f小数
console.log("%o",console); //%o表示对象
console.log("%c自定义样式","font-size:30px;color:#00f");
console.log("%c我是%c自定义样式","font-size:20px;color:green","font-size:10px;color:red");

DOM输出

1
2
var ul = document.getElementsByTagName("ul");
console.dirxml(ul)

对象输出

1
2
var o = {name:"Lily",age:18};
console.dir(obj)
1
2
3
var stu = [{name:"Bob",age:13,hobby:"playing"},{name:"Lucy",age:14,hobby:"reading"},{name:"Jane",age:11,hobby:"shopping"}];
console.log(stu);
console.table(stu);

成组输出

1
2
3
4
5
console.group("start"); // 引号里是组名
console.log("sub1");
console.log("sub1");
console.log("sub1");
console.groupEnd("end");

函数计数和跟踪

1
2
3
4
5
6
7
8
9
10
11
12
function fib(n){ // 输出前n个斐波那契数列值
if( n == 0) return;
console.count("调用次数"); // 放在函数里,每当这句代码运行输出所在函数执行次数
console.trace(); // 显示函数调用轨迹(访问调用栈)
var a = arguments[1] || 1;
var b = arguments[2] || 1;
console.log("fib=" + a);
[a, b] = [b, a + b];
fib(--n, a, b);
}

fib(6);

计时

1
2
3
console.time() // 计时开始
fib(100); // 用上述函数计算100个斐波那契数
console.timeEnd() // 计时结束并输出时长

断言语句

1
2
console.assert(true, "我错了");
console.assert(false,"我真的错了");
阅读更多

你的第一本Python基础入门书

Python

Python 优势

  • 上手容易、代码量更少、高效开发
  • 生态丰富、第三方库众多

语言核心特性

  • 数据类型
  • 数值运算和比较
  • 变量定义、赋值
  • 数组、字符串
  • 分支跳转
  • 循环
  • 函数

语言扩展特性

  • 异常机制
  • 模块与包
  • 内置数据结构
  • 内置函数
  • 迭代器
  • 生成器
  • 装饰器
  • 函数式特性
  • 动态类型
  • 以及其它常用语言特性

语言周边知识和功能

  • 标准库
  • IO 操作
  • 进程线程
  • 序列化
  • 代码规范
  • 以及运行环境相关,如 Python 解释器、虚拟环境,Java 的 JVM 等

扩展

为什么需要程序语言

计算机实际运行的是计算机指令序列。指令序列的直接表现形式是一连串的 0 和 1,也就是机器码。
用机器码的 0 和 1 这两个字符来编程是困难和低效的。为了提高生产效率,我们需要一种容易书写和阅读的标记来表达机器码指令。使用方式是用这种标记进行程序编码,编码完成后再将这些标记翻译为机器码。最初达到这个目的的是汇编语言,汇编语言一种是程序语言,不过是低级程序语言,它和机器码之间有着比较直接的一一对应关系。
扩展:计算机的世界里「抽象」这次词表示屏蔽掉内部纷繁复杂的细节,直接触达其核心功能,为外部建立起更高效更易用的使用入口和操作方法。

  • C 语言有非常高的执行效率,和马马虎虎的开发效率,在一些极度依赖执行效率和底层控制的领域独占鳌头,比如操作系统开发。
  • Java 借助于 JVM 得以跨越不同的操作系统和计算机架构而运行 Java 程序。Java 也拥有良好的执行效率和稳定性,它的执行效率与 C 语言相比,最高能保持在同一个数量级上。
  • Python 与 C 和 Java 相比有较大的不同,Python 是解释型语言,没有显式编译的过程,代码可直接由解释器解释执行,同时借助于解释器,其代码也可以跨平台运行。另一方面它是动态语言,在一定程度上更加灵活。Python 的理念是优雅和简单,虽然执行效率相较于 C 和 Java 大约慢一到两个数量级,不过 Python 的开发效率却数倍高于它们。

JavaScript中设计模式 从入门到实践应用

原生小程序中没有状态管理,看别人写状态管理需要观察者模式便来补一下。vue 中也使用了观察者模式,vue2 中用的 Object ……get、set 实现的。

构造器模式

用于在为其分配了内存后初始化新创建的对象。

1
2
3
4
5
6
7
function Car(model, year, miles) {
this.model = model;
this.year = year;
this.miles = miles;
}
// Usage:
var bmw = new Car('M4', '2019', '1000');

moModuleattern

  • 对象文字符号
  • 模块模式
  • AMD模块
  • CommonJS模块
  • ECMAScript Harmony模块
1
2
3
4
5
6
var newObject = {
variableKey:variableValue,
functionKey:function(){
//…
}
};

模块模式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var testModule = (function() {
var counter = 0;
return {
incrementCounter: function() {
return ++counter;
},
resetCounter: function() {
counter = 0;
}
};
})();
// Usage:
testModule.incrementCounter();
testModule.resetCounter();

显示模块模式

当我们要从另一个对象调用一个公共方法或访问公共变量时,避免重复主对象的名称

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var myRevealingModule = (function() {
var privateVariable = 'not okay',
publicVariable = 'okay';
function privateFun() {
return privateVariable;
}
function publicSetName(strName) {
privateVariable = strName;
}
function publicGetName() {
privateFun();
}
return {
setName: publicSetName,
message: publicVariable,
getName: publicGetName
};
})();
//Usage:
myRevealingModule.setName('Marvin King');

单例模式

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
var singletonPattern = (function() {
var instance;
function init() {
// Singleton
function privateMethod() {
console.log('privateMethod');
}
var privateVariable = 'this is private variable';
var privateRandomNumber = Math.random();
return {
publicMethod: function() {
console.log('publicMethod');
},
publicProperty: 'this is public property',
getRandomNumber: function() {
return privateRandomNumber;
}
};
}
return {
// Get the singleton instance if one exists
// or create if it doesn't
getInstance: function() {
if (!instance) {
instance = init();
}
return instance;
}
};
})();
// Usage:
var single = singletonPattern.getInstance();

观察者模式/发布-订阅模式

当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知依赖它的对象。观察者模式属于行为型模式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function ObserverList() {
this.observerList = [];
}
ObserverList.prototype.Add = function(obj) {
return this.observerList.push(obj);
};
ObserverList.prototype.Empty = function() {
this.observerList = [];
};
ObserverList.prototype.Count = function() {
return this.observerList.length;
};
ObserverList.prototype.Get = function(index) {
if (index > -1 && index < this.observerList.length) {
return this.observerList[index];
}
};
//...

中介者模式

中介体模式通过确保组件而不是彼此明确引用来促进松散耦合。

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
var mediator = (function() {
var topics = {};
var subscribe = function(topic, fn) {
if (!topics[topic]) {
topics[topic] = [];
}
topics[topic].push({ context: this, callback: fn });
return this;
};
// publish/broadcast an event to the rest of the application
var publish = function(topic) {
var args;
if (!topics[topic]) {
return false;
}
args = Array.prototype.slice.call(arguments, 1);
for (var i = 0, l = topics[topic].length; i < l; i++) {
var subscription = topics[topic][i];
subscription.callback.apply(subscription.content, args);
}
return this;
};
return {
publish: publish,
subscribe: subscribe,
installTo: function(obj) {
obj.subscribe = subscribe;
obj.publish = publish;
}
};
})();

原型模式

1
2
3
4
5
6
7
8
9
10
11
12
var myCar = {
name: 'bmw',
drive: function() {
console.log('I am driving!');
},
panic: function() {
console.log('wait, how do you stop this thing?');
}
};
//Usages:
var yourCar = Object.create(myCar);
console.log(yourCar.name); //'bmw'

工厂模式

1
2
3
4
5
function Car(options) {
this.doors = options.doors || 4;
this.state = options.state || 'brand new';
this.color = options.color || 'silver';
}

Mixin模式

混合类是提供功能的类,这些功能可以由子类或子类组轻松继承以进行功能复用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var Person = function(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
this.gender = 'male';
};
var clark = new Person('Clark', 'kent');

var Superhero = function(firstName, lastName, powers) {
Person.call(this.firstName, this.lastName);
this.powers = powers;
};
SuperHero.prototype = Object.create(Person.prototype);
var superman = new Superhero('Clark', 'Kent', ['flight', 'heat-vision']);
console.log(superman); //output personal attributes as well as power

装饰器模式

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
function MacBook() {
this.cost = function() {
return 997;
};
this.screenSize = function() {
return 11.6;
};
}
// Decorator 1
function Memory(macbook) {
var v = macbook.cost();
macbook.cost = function() {
return v + 75;
};
}
// Decorator 2
function Engraving(macbook) {
var v = macbook.cost();
macbook.cost = function() {
return v + 200;
};
}
// Decorator 3
function Insurance(macbook) {
var v = macbook.cost();
macbook.cost = function() {
return v + 250;
};
}
var mb = new MacBook();
Memory(mb);
Engraving(mb);
Insurance(mb);
mb.cost(); // 1522

10个每个开发人员都喜欢的JavaScript模式
菜鸟教程 观察者模式
JavaScript 设计模式与开发实践 第8章
不知道怎么封装代码?看看这几种设计模式吧!
JavaScript 设计模式学习总结与感悟

You need to set client_id and slot_id to show this AD unit. Please set it in _config.yml.