正则表达式

定义

正则表达式是一种描述字符串数据模式的方法,是检查、处理字符串的强力工具。

创建正则表达式

var re1 = new RegExp(“abc”);
var re2 = /abc/;

使用构造函数创建时,反斜杠的使用规则与往常相同。
使用双斜杠字面值创建时,不确定字符是否具有特殊含义,而不是字母、数字、空格式,只要在字符前加上反斜杠即可。

匹配测试

test方法

接受用户传递的字符串,并返回一个布尔值,表示字符串中是否包含能与表达式模式匹配的字符串。

var re2 = /abc/;
console.log(re2.test('abcde'));
// > true
console.log(re2.test('abxde'));
// > false

exec方法

如果无法匹配模式则返回null,否则返回一个表示匹配字符串信息的对象。
exec方法返回的对象中包含index属性,表示字符串成功匹配的起始位置。

var re2 = /abc/;
console.log(re2.exec('abcde'));
// > ["abc", index: 0, input: "abcde"]
console.log(re2.exec('abxde'));
// > null

若正则表达式中包含圆括号的子表达式分组,与这些分组匹配的文本也会出现在数组中。
第一个元素是与整个模式匹配的字符串,
其后是与第一个分组匹配的部分字符串,然后是第二个分组如此类推。

var dataTimeRE = /(\d{1,2})-(\d{1,2})-(\d{4})/;
var str = '24-8-2016';
var match = dataTimeRE.exec(str);
console.log(match);

// > ["24-8-2016", "24", "8", "2016", index: 0, input: "24-8-2016”]

字符组快捷写法

  • \d --数字符号
  • \w --字母和数字符号
  • \s --空白符号(空格,制表符,换行符等)
  • \D --非数字符号
  • \W --非字母和数字符号
  • \S --非空白符号
    . --除了换行符以外的任意符号

    部分模式重复

  • + --该元素至少重复一次
  • * --该元素至少重复一次,同时可以匹配模式不存在的情况
  • ? --可选,模式出现0次或1次
  • { } --指明模式出现的次数。{4},4次。{2,4},2~4次。{,4},0~4次。{4.},至少4次以上。

    边界

  • ^ --字符始位置
  • $ --字符结束位置
  • \b --单词边界( \w 集合)
    /^\d+$/:匹配一个或者多个数字组成的字符串。
    /^!/ :匹配任何以感叹号开头的字符串。
    /x^/ :不匹配任何字符串。

子表达式分组

如果一次性相想对多个元素使用*或者+,那么就需要使用分组。

var strRE = /boo+(hoo+)+/i;
var str = 'Booooohooooohoohoooo';
var test = strRE.test(str);
console.log(test);
// > true

选项模式

管道符号(|),表示从其左侧的模式和右侧的模式任意选择一个进行匹配。

var animalCount = /\b\d+ (pig|cow|chicken)s?\b/;
console.log(animalCount.test("15 cows"));
// > true

用例

检查手机号码

function isMobile(tel){
     return /^((\(\d{2,3}\))|(\d{3}\-))?(1[34578]\d{9})$/.test(tel);
}

获取URL的Query参数

function getQuery(name) {
    var result = location.search.match(new RegExp("[\?\&]" + name+ "=([^\&]+)","i"));
    if(result == null || result.length < 1){
        return "";
    }
    return result[1];
}

拆分host后缀

function domainarr(url){
     var durl = /http:\/\/([^\/]+)\//i;
     var hosts = url.match(durl);
     var d_arr;
     hosts = hosts[1];
     d_arr = hosts.split('.');
     return d_arr;
}

定义

在学习ES6中挑选出比较常用、实用的部分。

  • var、let、const
    let和const的出现,应该就是为了替代var吧,能使代码结构更加之严谨。

  • let用于声明变量,const用于声明常量。
    意思就是let可以重新赋值,const则不能,并且const声明就必须赋值。

    let a =1;
    a = 2;
    // 2
    const b = 1;
    b = 2;
    // Identifier 'a' has already been declared
    let a ;
    // undefind
    const b ;
    // Missing initializer in const declaration
  • 块级作用域

    if(true){
      var a = 3;
    }
    console.log(a)
    //  3
    if(true){
      let b = 3;
    }
    console.log(b)
    // Uncaught ReferenceError: b is not defined
  • 不允许重复声明
    在一定程度上防止了变量污染

    let a = 1;
    var a = 2;  // or const a = 3;let a = 4;
    // Identifier 'a' has already been declared
  • 不存在变量提升

    console.log(a)
    var a =1;
    // undefind
    console.log(b)
    let b =1;
    // Uncaught ReferenceError: a is not defined
  • 暂存性死区
    在当前的块级作用域中声明,即代表绑定了该环境,在当前环境中声明前赋值都会报错。因为在这个区域不支持变量提升。

    
    var  a = 3;
    if(true){
      a =4;
      let a;
    }
    console.log(a)
    // Uncaught ReferenceError: a is not defined

最外层不再是window

var a = 1;
let b = 1;
const c = 1;
console.log(window.a) // 1
console.log(window.b) // undefined
console.log(window.c) // undefined

- 模版字符串
在拼接HTML插入DOM的时候,功效尤其显著。
``` javascript
// ES5
var name = 'jax';
var say = 'hello,'+name+'.'+'Nice to meet you!'
// ES6
var name = 'jax';
var say = `hello,${name}.Nice to meet you!`
  • 函数默认值
    在ES6之前,不能直接为函数的参数指定默认值,只能采用变通的方法。
    //ES5
    (function log(x) {
    x = x || 'Hello';
    console.log(x);
    })();
    // ES6
    (function log( x = 'Hello') {
    console.log(x);
    })();

模块化

伴随着移动互联的大潮,当今越来越多的网站已经从网页模式进化到了 Webapp 模式。它们运行在现代的高级浏览器里,使用 HTML5、 CSS3、 ES6 等更新的技术来开发丰富的功能,网页已经不仅仅是完成浏览的基本需求,并且webapp通常是一个单页面应用,每一个视图通过异步的方式加载,这导致页面初始化和使用过程中会加载越来越多的 JavaScript 代码,这给前端开发的流程和资源组织带来了巨大的挑战。

前端开发和其他开发工作的主要区别,首先是前端是基于多语言、多层次的编码和组织工作,其次前端产品的交付是基于浏览器,这些资源是通过增量加载的方式运行到浏览器端,如何在开发环境组织好这些碎片化的代码和资源,并且保证他们在浏览器端快速、优雅的加载和更新,就需要一个模块化系统,这个理想中的模块化系统是前端工程师多年来一直探索的难题。

定义:

模块通过将代码分割成不同文件和命名空间,为更大规模的程序提供了结构。

模块系统的演进
模块系统主要解决模块的定义、依赖和导出,先来看看已经存在的模块系统。

script标签

<script src="module1.js"></script>
<script src="module2.js"></script>
<script src="libraryA.js"></script>
<script src="module3.js"></script>

这是最原始的 JavaScript 文件加载方式,如果把每一个文件看做是一个模块,那么他们的接口通常是暴露在全局作用域下,也就是定义在 window 对象中,不同模块的接口调用都是一个作用域中,一些复杂的框架,会使用命名空间的概念来组织这些模块的接口,典型的例子如 YUI 库。

这种原始的加载方式暴露了一些显而易见的弊端:

  • 全局作用域下容易造成变量冲突
  • 文件只能按照 script 的书写顺序进行加载
  • 开发人员必须主观解决模块和代码库的依赖关系
  • 在大型项目中各种资源难以管理,长期积累的问题会导致代码库混乱

CommonJS

服务器端的 Node.js 遵循 CommonJS规范,该规范的核心思想是允许模块通过 require 方法来同步加载所要依赖的其他模块,然后通过 exports 或 module.exports 来导出需要暴露的接口。

require("module");
require("../file.js");
exports.doStuff = function() {};
module.exports = someValue;

优点:

服务器端模块便于重用
NPM 中已经有将近20万个可以使用模块包
简单并容易使用

缺点:

同步的模块加载方式不适合在浏览器环境中,同步意味着阻塞加载,浏览器资源是异步加载的
不能非阻塞的并行加载多个模块

实现:

服务器端的 Node.js
Browserify,浏览器端的 CommonJS 实现,可以使用 NPM 的模块,但是编译打包后的文件体积可能很大
modules-webmake,类似Browserify,还不如 Browserify 灵活
wreq,Browserify 的前身

AMD

Asynchronous Module Definition 规范其实只有一个主要接口 define(id?, dependencies?, factory),它要在声明模块的时候指定所有的依赖 dependencies,并且还要当做形参传到 factory 中,对于依赖的模块提前执行,依赖前置。

define("module", ["dep1", "dep2"], function(d1, d2) {
  return someExportedValue;
});
require(["module", "../file"], function(module, file) { /* ... */ });

优点:

适合在浏览器环境中异步加载模块
可以并行加载多个模块

缺点:

提高了开发成本,代码的阅读和书写比较困难,模块定义方式的语义不顺畅
不符合通用的模块化思维方式,是一种妥协的实现

实现:

RequireJS
curl

CMD

Common Module Definition 规范和 AMD 很相似,尽量保持简单,并与 CommonJS 和 Node.js 的 Modules 规范保持了很大的兼容性。

define(function(require, exports, module) {
  var $ = require('jquery');
  var Spinning = require('./spinning');
  exports.doSomething = ...
  module.exports = ...
})

优点:

依赖就近,延迟执行
可以很容易在 Node.js 中运行

缺点:

依赖 SPM 打包,模块的加载逻辑偏重

实现:

Sea.js
coolie

UMD

Universal Module Definition 规范类似于兼容 CommonJS 和 AMD 的语法糖,是模块定义的跨平台解决方案。

ES6 模块

EcmaScript6 标准增加了 JavaScript 语言层面的模块体系定义。ES6 模块的设计思想,是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。CommonJS 和 AMD 模块,都只能在运行时确定这些东西。

import "jquery";
export function doStuff() {}
module "localModule" {}

优点:

容易进行静态分析
面向未来的 EcmaScript 标准

缺点:

原生浏览器端还没有实现该标准
全新的命令字,新版的 Node.js才支持

实现:

Babel

前端模块化

前端模块要在客户端中执行,所以他们需要增量加载到浏览器中。

模块的加载和传输,我们首先能想到两种极端的方式,一种是每个模块文件都单独请求,另一种是把所有模块打包成一个文件然后只请求一次。显而易见,每个模块都发起单独的请求造成了请求次数过多,导致应用启动速度慢;一次请求加载所有模块导致流量浪费、初始化过程慢。这两种方式都不是好的解决方案,它们过于简单粗暴。

分块传输,按需进行懒加载,在实际用到某些模块的时候再增量更新,才是较为合理的模块加载方案。

要实现模块的按需加载,就需要一个对整个代码库中的模块进行静态分析、编译打包的过程。

强制使用https
server {  
    listen  192.168.1.111:80;  
    server_name test.com;  

    rewrite ^(.*)$  https://$host$1 permanent;  
}  

nginx -s reload  :修改配置后重新加载生效
nginx -s reopen  :重新打开日志文件
nginx -t -c /path/to/nginx.conf 测试nginx配置文件是否正确

关闭nginx:
nginx -s stop  :快速停止nginx
         quit  :完整有序的停止nginx

其他的停止nginx 方式:

ps -ef | grep nginx

kill -QUIT 主进程号     :从容停止Nginx
kill -TERM 主进程号     :快速停止Nginx
pkill -9 nginx          :强制停止Nginx


启动nginx:
nginx -c /path/to/nginx.conf

平滑重启nginx:
kill -HUP 主进程号