Map
// map
var m = new Map([['michael', 54],['lily', 32]])
m.get('michael') //54
m.set('lily', 18)
m.get('lily') //18
m.delete('lily')
m.get('lily') //undefined
// Set和Map类似,也是一组key的集合,但不存储value。由于key不能重复,所以,在Set中,没有重复的key。
var s = new Set([1, 2, 3])
s.add(4)
console.log(s) // [1, 2, 3, 4]
s.delete(2)
console.log(s) // [1, 3, 4]
// 转换格式取值
var m=new Map();
var n=[['po',10],['sd',20],['cz',30],['bf',40],['as',50]];
for(var i=0;i<n.length;i++){
m.set(n[i][0],n[i][1])
}
var look=m.get('po');
alert(look);
// 可用于数组去重
var arr = [1,2,1,2,2,1];
//new Set 数组去重
function unique(arr){
return Array.from(new Set(arr));
};
//使用ES6的方法可以去重.
console.log(unique(arr));
Array.from的妙用
es6新特性中Array类多了一个静态方法from,这个方法作用是将一个ArrayLike对象或者Iterable对象转换成一个Array,本文只讨论ArrayLike对象相关内容。
Iterable
遍历Array可以采用下标循环,遍历Map和Set就无法使用下标。为了统一集合类型,ES6标准引入了新的iterable类型,Array、Map和Set都属于iterable类型。
具有iterable类型的集合可以通过新的for ... of循环来遍历。
高阶函数
map/reduce
arr.map((element, index, self) => ) arr.reduce((x, y) => )
// 要把[1, 3, 5, 7, 9]变换成整数13579,reduce()也能派上用场:
var arr = [1, 3, 5, 7, 9]
arr.reduce((x, y) => x*10+y)
// 请把用户输入的不规范的英文名字,变为首字母大写,其他小写的规范名字。输入:['adam', 'LISA', 'barT'],输出:['Adam', 'Lisa', 'Bart']。
function normalize(arr){
return arr.map((name) => name[0].toUpperCase() + name.substring(1).toLowerCase())
}
filter
arr.filter((element, index, self) => )
// filter 所需参数
var arr = ['A', 'B', 'C'];
var r = arr.filter(function (element, index, self) {
console.log(element); // 依次打印'A', 'B', 'C'
console.log(index); // 依次打印0, 1, 2
console.log(self); // self就是变量arr
return true;
});
// filter 去重
var r,arr = ['apple', 'apple', 'pear', 'grape', 'banana'];
r = arr.filter((element, index, self) => self.indexOf(element) === index)
console.log(r)
// 用filter()筛选出素数:
function get_primes(arr) {
return arr.filter(element =>element<2? false : !/^(11+?)\1+$/.test(Array(element + 1).join('1')));
}
function get_primes(arr) {
return arr.filter(function (x) {
if (x < 2) return false;
for (var temp = 2; temp < x; temp++) {
if (x % temp === 0) {
return false;
}
}
return true;
})
}
sort
var arr = [10, 20, 1, 2];
arr.sort(function (x, y) {
if (x < y) {
return 1;
}
if (x > y) {
return -1;
}
return 0;
}); // [20, 10, 2, 1]
箭头函数的作用
箭头函数和匿名函数有个明显的区别:箭头函数内部的this是词法作用域,由上下文确定。
var obj = {
birth: 1990,
getAge: function () {
var b = this.birth // 1990
var fn = function () {
return new Date().getFullYear() - this.birth; //this指向window或undefined
}
}
}
现在,箭头函数完全修复了this的指向,this总是指向 词法作用域
,也就是外层调用者obj:
var obj = {
birth: 1990,
getAge: function () {
var b = this.birth // 1990
var fn = () => new Date().getFullYear() - this.birth
return fn
}
}
obj.getAge(); // 25
由于this在箭头函数中已经按照 词法作用域
绑定了,所以,用call()或者apply()调用箭头函数时,无法对this进行绑定,即传入的第一个参数被忽略:
var obj = {
birth: 1990,
getAge: function (year) {
var b = this.birth; // 1990
var fn = (y) => y - this.birth; // this.birth仍是1990
return fn.call({birth:2000}, year);
}
};
obj.getAge(2015); // 25
// method1 递归法
function aaa(n){
if(n <= 2) return 1
return aaa(n-1) + aaa(n-2)
}
// 迭代法
function aaa(n) {
var num1 = 1
var num2 = 1
var num3 = 0
for(var i=0;i < n-2;i++){
num3 = num1 + num2
num1 = num2
num2 = num3
}
return num3
}
// 测试:
fib(5); // [0, 1, 1, 2, 3]
fib(10); // [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
标准对象
更细心的同学指出,number对象调用toString()报SyntaxError:
123.toString(); // SyntaxError
遇到这种情况,要特殊处理一下:
123..toString(); // '123', 注意是两个点!
12.3.toString(); // 12.3
(123).toString(); // '123'
Date
你可能观察到了一个非常非常坑爹的地方,就是JavaScript的月份范围用整数表示是0~11,0表示一月,1表示二月……
第二种创建一个指定日期和时间的方法是解析一个符合ISO 8601格式的字符串:
var now = new Date();
now; // Wed Jun 24 2015 19:49:22 GMT+0800 (CST)
now.getFullYear(); // 2015, 年份
now.getMonth(); // 5, 月份,注意月份范围是0~11,5表示六月
now.getDate(); // 24, 表示24号
now.getDay(); // 3, 表示星期三
now.getHours(); // 19, 24小时制
now.getMinutes(); // 49, 分钟
now.getSeconds(); // 22, 秒
now.getMilliseconds(); // 875, 毫秒数
now.getTime(); // 1435146562875, 以number形式表示的时间戳
var d = Date.parse('2015-06-24T19:49:22.875+08:00');
d; // 1435146562875
但它返回的不是Date对象,而是一个时间戳。不过有时间戳就可以很容易地把它转换为一个Date:
var d = new Date(1435146562875);
d; // Wed Jun 24 2015 19:49:22 GMT+0800 (CST)
RegExp
要匹配变长的字符,在正则表达式中,用 *
表示任意个字符(包括0个),用 +
表示至少一个字符,用 ?
表示0个或1个字符,用 {n}
表示n个字符,用 {n,m}
表示n-m个字符:
来看一个复杂的例子: \d{3}\s+\d{3,8}
。
我们来从左到右解读一下:
\d{3}
表示匹配3个数字,例如'010'
;\s
可以匹配一个空格(也包括Tab等空白符),所以\s+
表示至少有一个空格,例如匹配' '
,'\t\t'
等;\d{3,8}
表示3-8个数字,例如'1234567'
。
综合起来,上面的正则表达式可以匹配以任意个空格隔开的带区号的电话号码。
如果要匹配 '010-12345'
这样的号码呢?由于 '-'
是特殊字符,在正则表达式中,要用 '\'
转义,所以,上面的正则是 \d{3}\-\d{3,8}
。
但是,仍然无法匹配 '010 - 12345'
,因为带有空格。所以我们需要更复杂的匹配方式。
进阶
要做更精确地匹配,可以用 []
表示范围,比如:
[0-9a-zA-Z\_]
可以匹配一个数字、字母或者下划线;[0-9a-zA-Z\_]+
可以匹配至少由一个数字、字母或者下划线组成的字符串,比如'a100'
,'0_Z'
,'js2015'
等等;[a-zA-Z\_\$][0-9a-zA-Z\_\$]*
可以匹配由字母或下划线、$开头,后接任意个由一个数字、字母或者下划线、$组成的字符串,也就是JavaScript允许的变量名;[a-zA-Z\_\$][0-9a-zA-Z\_\$]{0, 19}
更精确地限制了变量的长度是1-20个字符(前面1个字符+后面最多19个字符)。
A|B
可以匹配A或B,所以 (J|j)ava(S|s)cript
可以匹配 'JavaScript'
、'Javascript'
、'javaScript'
或者 'javascript'
。
^
表示行的开头, ^\d
表示必须以数字开头。
$
表示行的结束, \d$
表示必须以数字结束。
你可能注意到了, js
也可以匹配 'jsp'
,但是加上 ^js$
就变成了整行匹配,就只能匹配 'js'
了。
切分字符串
用正则表达式切分字符串比用固定的字符更灵活,请看正常的切分代码:
'a b c'.split(' '); // ['a', 'b', '', '', 'c']
嗯,无法识别连续的空格,用正则表达式试试:
'a b c'.split(/\s+/); // ['a', 'b', 'c']
无论多少个空格都可以正常分割。加入 ,
试试:
'a,b, c d'.split(/[\s\,]+/); // ['a', 'b', 'c', 'd']
再加入 ;
试试:
'a,b;; c d'.split(/[\s\,\;]+/); // ['a', 'b', 'c', 'd']
如果用户输入了一组标签,下次记得用正则表达式来把不规范的输入转化成正确的数组。
验证 邮箱
试试:
var re = / ^\w+[.]?\w+@\w+.\w+$ /;
var re = / ^\w+.?\w+@\w+.\w+$ /;
var re = / (<\w+\s\w+?>)\s(\w+.?\w+@\w+.\w+) /;