ES2015入门系列7-模版字符串

说到 模版字符串 (Template strings or Template literals), 我们先来看看在ES5中,我们遇到的问题:

假设我们需要拼接一段html字符串,常规的做法如下:

1
2
3
4
5
6
var text = 'ES5 sucks!';
var html = '\
<div> \
<p>' + text + '</p>\
</div>';
console.log(html);

或者:

1
2
3
4
5
6
7
var text = 'ES5 sucks!';
var html = [
'<div>',
'<p>' + text + '</p>',
'</div>'
].join('');
console.log(html);

写的很难受对不对?到了ES2015, 有了 模版字符串 后,事情就变得简单了。

模版字符串,就是用 `` 包裹起来的字符串, 如:

1
2
3
4
5
6
let html = `
<div>
<p>ES5 sucks!</p>
</div>
`;
console.log(html);

在其中,我们还可以使用 ${变量名}, 直接引用变量,而不用字符串拼接了,如:

1
2
3
4
5
6
7
let text = 'ES5 sucks!';
let html = `
<div>
<p>${text}</p>
</div>
`;
console.log(html);

查看全文

ES2015入门系列6-Rest和Spread

ES2015为我们带来了一个新的操作符: ,

  • 用于定义函数参数的地方,称之为 Rest
  • 用于调用函数的地方,称之为 Spread

我们一个个来分析:

  • Rest

写程序的时候或多或少都会有,传入不定参数给一个函数的需求,如,给一个班级加入学生名单,可以一次给一个,也可以一次给多个,以前的做法,可能是传入数组,或者定义2个方法,一个传入单个学生,一个传入学生数组,如:

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
class ClassRoom {
constructor(name) {
this.name = name;
this.students = [];
}
addStudent(name) {
this.students.push(name);
}
addStudents(names) {
this.students = this.students.concat(names);
}
listStudents() {
console.log(this.students);
}
}
const classRoom = new ClassRoom('三年二班');
classRoom.addStudent('张三');
classRoom.addStudents(['李四', '王五']);
classRoom.listStudents();

有了 Rest 我们的代码就简单了,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class ClassRoom {
constructor(name) {
this.name = name;
this.students = [];
}
addStudents(...names) {
this.students = this.students.concat(names);
}
listStudents() {
console.log(this.students);
}
}
const classRoom = new ClassRoom('三年二班');
classRoom.addStudents('张三');
classRoom.addStudents('李四', '王五');
classRoom.listStudents();

代码中的…names, 意思就是: 从我开始不管后面有多少参数,请帮我把它们组成数组给我后面的参数。 如此一来,也可以这样,

1
2
3
4
5
function callFriends(via, ...friends) {
console.log('使用' + via + '通知: ' + friends.join(',') + '等' + friends.length + '个好友');
}
callFriends('QQ', '张三');
callFriends('电话', '张三', '李四', '王五');

查看全文

ES2015入门系列5-解构赋值

用过ReactNative的同学肯定见过类似下面的代码:

1
import { Text, View } from 'react-native';

这就是ES2015为JavaScript带来的另一个新的语法:解构赋值。

解构赋值(Destructuring assignment), 是用来让我们从数组或者对象中提取数据赋值给不同的变量。

语法如下:

  • 从数组中解构赋值
1
let [a, b] = [1, 2];
  • 从对象中解构赋值
1
let {a, b} = {a: 1, b: 2}

PHP开发者有没有觉得很眼熟? 对了,这不就是:

查看全文

ES2015入门系列4-参数默认值

这个功能比较简单,但对于后端开发来说,会觉得会奇怪,参数默认值还需要特殊支持么?答案是肯定的,在ES5中, 参数是不可以指定默认值的,统一默认为 undefined, 如下代码:

1
2
3
4
5
6
7
function say(word) {
word = word || '呵呵!';
console.log(word);
}
console.log(say()); //呵呵!
console.log(say('哈哈!')); //哈哈!

没错,ES2015之前,我们只能这么来操作参数默认值,但是在ES2015中,就不再需要啦,就和普通的后端语言一样:

1
2
3
4
5
6
function say(word = '呵呵!') {
console.log(word);
}
console.log(say()); //呵呵!
console.log(say('哈哈!')); //哈哈!

是不是就这么结束啦?当然不是,回到官方手册上,我们看到的是:

Callee-evaluated default parameter values.

参数默认值是被计算过的,意味着,我们可以写表达式,这个也是其他语言做不到的,看代码:

1
2
3
4
5
6
7
8
9
10
function defaultWord() {
return '呵呵!';
}
function say(word = defaultWord()) {
console.log(word);
}
console.log(say()); //呵呵!
console.log(say('哈哈!')); //哈哈!

什么叫evaluated, 其实也就是在应用默认值的时候,相当于JavaScript编译器使用eval计算一下,出来的结果当作默认值:

1
2
3
function say(word = eval('"呵呵!"')) {
console.log(word);
}

查看全文

ES2015入门系列3-箭头函数

箭头函数(Arrows), 是用新的 => 语法书写的匿名函数, 如:

1
[1, 2, 3].map(n => n + 1);

等同于下面使用ES5的写法:

1
2
3
[1, 2, 3].map(function(n) {
return n + 1;
});

可能一开始无法接受,但慢慢的会发现箭头函数带来的快感不言而喻。作为一个PHP后端人士希望PHP也能支持该语法, 😄。

  • 一般写法, 如计算两个数字之和, 并返回:
1
2
3
4
(arg1, arg2) => {
let arg3 = arg1 + arg2
return arg3
}

不用写function关键字, 但是上面的写法,也感觉不出来有多少简化,我们来看看几种情况:

  • 如果只有一个参数,可以不用写括号
1
2
3
n => {
return n + 1
}

查看全文

ES2015入门系列2-let和const

ES2015 新增了两个变量修饰关键字:

  • let
  • const

它们都是块级别的,那什么是块?简单的来说,块就是一组花括号中间的部分。

  • Var

为了理解let我们先从var说起,如下代码:

1
2
3
4
5
6
7
8
9
10
function checkStatus(status) {
if (status) {
var statusLabel = 'ok';
console.log(statusLabel);
} else {
console.log(statusLabel);
}
}
checkStatus(true);
checkStatus(false);

在 Chrome Console 中运行后,获得结果:

1
2
ok
undefined

我们在false条件中加入一行代码:

1
2
3
4
5
6
7
8
9
10
11
function checkStatus(status) {
if (status) {
var statusLabel = 'ok';
console.log(statusLabel);
} else {
console.log(statusLabel);
console.log(abc);//执行后会输出: Uncaught ReferenceError: abc is not defined(…)
}
}
checkStatus(true);
checkStatus(false);

查看全文

ES2015入门系列1-初识ES2015

EcmaScript 其实是一种语言规范,常见的 JavaScript, ActionScript 等都是其具体实现,平时使用中一般可以将其和Javascript对等称呼,本系列教程主要讲述 EcmaScript2015(ES6) 为JavaScript带来的新的特性,并初步掌握如何利用其进行开发。

本系列面向有一定基础知识的ES5使用者,不适合初学者。

先来看两段代码:

Human.js

1
2
3
export default class Human {
}

main.js

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
import Human from './Human';
class Man extends Human {
constructor(name = 'unnamed') {
super();
this.gender = 'male';
this.name = name;
}
static create(name = 'unamed') {
return new Man(name);
}
getGender() {
return this.gender;
}
getName() {
return this.name;
}
}
const man = new Man('Jack');
let manObject = {
man
}
console.log(man.getName());
console.dir(manObject);

上面的代码为我们展示了和ES5不一样的语法:

  • importexport

    模块化开发,在此之前也有很多的方案,AMD, CMD等,但从使用上来说,ES2015的模块化开发还是很简单和强大的。

  • class

    语意化的的面向对象语法,不过不要惊讶,这其实只是语法糖,在其背后,依然是编译器按照ES5的方式去执行的,不过对于后端开发者来说,接受起来就不会那么难受了。class中定义方法无需function关键字, 这些会在后面的章节进一步讲解。

  • 参数有默认值了

    不用再使用:

    1
    a = a || 'default';

    这种方式处理默认值啦,其实这也是语法糖,但是带来的便利不言而喻。

  • constlet 关键字

    var 终于不再一家独大了,来了2个小伙伴一起玩耍。

  • 属性简洁写法

    如果对象的属性名称和变量名称一致,那么可以使用下面的简洁写法:

    1
    2
    3
    4
    5
    6
    7
    8
    let manObject = {
    man
    }
    //等同于
    let manObject = {
    man: man
    }

怎么样,相比ES5,是不是更现代化了呢?

查看全文

Hexo插件之Hexo-UUID

在我之前的博客搬迁纪录中,提到:

Hexo 每次 generate 后 post._id 会变化,导致和多说关联无效,评论无法显示

我的解决方法是给每篇文章手动增加了uuid属性,手动 不符合程序猿懒的个性,不如写个插件了。

有朋友也许会问为什么不用 permanent link 或者 创建时间戳 等作为关联媒介,我想这2个对于我来说都可能不是一直不变的,所以我更倾向于一个我不会去改变的属性,😄。

废话不多说,开始写代码,看完一遍 Hexo API 文档后,可以从 Hexo创建文章后的事件这里入手,Hexo创建文章后会触发new事件,同时携带文章的结构体作为参数:

1
2
3
4
{
"path": "/the/path/your/post/will/stored/in",
"content": "---\ntitle: some title\ndate: 2016-05-20 22:00\ntags:\n---\n"
}

解决方案就是修改此处post内容,并写入path指向的文件地址。

码代码开始,这里就只用ES2015语法写了:

index.js:

1
2
3
4
5
'use strict';
const HexoUuid = require('./lib/hexo-uuid');
hexo.on('new', HexoUuid);

查看全文

caddy服务器初识

今天给大家介绍一个不一样的服务器软件, 基于Go语言编写的Caddy

The HTTP/2 web server with automatic HTTPS

宣传语很有意思,两个关键词: HTTP/2automatic HTTPS

  • HTTP/2

    这是在去年正式发布的新一代 HTTP 协议,是由 SPDY 协议演变而来的,SPDY完成其使命之后,Chrome也已经宣布停止支持该协议,未来无疑就是HTTP/2的天下了, 它的好处很多,感兴趣的可以参考:

  • automatic HTTPS

    自动https部署,在其背后是Caddy自动帮我们在Let’s Encrypt 帮我们完成证书的申请并自动应用起来。Let’s Encrypt 证书申请部署虽然不是很复杂,但这种简易的自动化操作带来的方便感还是不言而喻的,大家可以对比下Nginx下部署的过程,参考 JerryQu的文章

当然Caddy还支持很多功能:

  • IPv6
  • Markdown
  • WebSockets
  • FastCGI
  • templates
  • more…

具体参考其手册

最后,我们来看下我的博客的部署配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
https://www.chekun.me, http://www.chekun.me, http://chekun.me {
redir https://chekun.me{uri}
tls mr.che.kun@gmail.com
}
https://chekun.me {
gzip
log /var/log/caddy/chekun.me.access.log
tls mr.che.kun@gmail.com
root /data/chekun.me/
header / {
Strict-Transport-Security: "max-age=10886400; includeSubDomains; preload"
X-Frame-Options "deny"
Cache-Control "public*"
X-Content-Type-Options "nosniff"
}
}

是不是超级简单而且非常易懂?

查看全文

博客搬迁记录

近期将博客从 vultr VPS迁移到阿里云,并使用 Hexo 替代原来的 Typecho 程序。

虽然阿里云备案体验做的很好了,但是还是不得不大声的说一句:

备案太坑爹啦 !!!

言归正传:

  • Hexo 替换 Typecho, Typecho 中也是使用 Markdown 书写,迁移过来很简单,日志十来篇就复制粘贴喽
  • 服务器弃了 Nginx, 用了更好玩的 Caddy,主要看中其 Automatic HTTPS 的功能
  • 恢复 多说, 并将之前的评论和新的URL一一对应
  • 多说 中部分的资源并不是https, 所以直接 block掉了,还是喜欢绿🔒!
  • 对默认的样式进行了小幅修改

最后:

后面要认真写博客啦,欢迎大家常来玩!

updated

Hexopost._id 每次generate的时候会变,所以不能用做和多说绑定的唯一标识,我的方案是用增加一个 UUID 替换。如

1
2
3
4
5
---
uuid: 8731fea9-d3b4-43a6-b701-05397716e8fd
title: 博客搬迁记录
...
---

查看全文