1.for...in
for循环的一个变体是for ... in循环,它可以把一个对象的所有属性依次循环出来:
其实,更好的方式是直接使用iterable内置的forEach方法,它接收一个函数,每次迭代就自动回调该函数:
最新的ES6规范引入了新的数据类型Map和Set.
(1)Map
Map是一组键值对的结构。
Set和Map类似,也是一组key的集合,但不存储value。
ES6标准引入了新的iterable类型,Array、Map和Set都属于iterable类型。
具有iterable类型的集合可以通过新的for ... of循环来遍历:
ES6标准引入了rest参数,如下:
4.高阶函数
一个函数可以接收另一个函数作为参数,这种函数就称之为高阶函数。
ES6标准新增了一种新的函数:Arrow Function(箭头函数)。
箭头函数相当于匿名函数,简化了函数定义。
箭头函数还有一个作用,完全修复了this的指向,this总是指向词法作用域,也就是外层调用者obj:
generator(生成器)是ES6标准引入的新的数据类型。
generator跟函数很像,定义如下:
“承诺将来会执行”的对象在JavaScript中称为Promise对象。
for循环的一个变体是for ... in循环,它可以把一个对象的所有属性依次循环出来:
var o = {
name: 'Jack',
age: 20,
city: 'Beijing'
};
for (var key in o) {
alert(key); // 'name', 'age', 'city'
}
要过滤掉对象继承的属性,用hasOwnProperty()来实现:
var o = {
name: 'Jack',
age: 20,
city: 'Beijing'
};
for (var key in o) {
if (o.hasOwnProperty(key)) {
alert(key); // 'name', 'age', 'city'
}
}
由于Array也是对象,而它的每个元素的索引被视为对象的属性,因此,for ... in循环可以直接循环出Array的索引:
var a = ['A', 'B', 'C'];
for (var i in a) {
alert(i); // '0', '1', '2'
alert(a[i]); // 'A', 'B', 'C'
}
注意:for ... in对Array的循环得到的是String, 而不是Number。
其实,更好的方式是直接使用iterable内置的forEach方法,它接收一个函数,每次迭代就自动回调该函数:
var a = ['A', 'B', 'C'];
a.forEach(function (element, index, array) {
// element: 指向当前元素的值
// index: 指向当前索引
// array: 指向Array对象本身
alert(element);
});
2.Map和Set
最新的ES6规范引入了新的数据类型Map和Set.
(1)Map
Map是一组键值对的结构。
var m = new Map([['Michael', 95], ['Bob', 75], ['Tracy', 85]]);
m.get('Michael'); // 95
Map具有以下方法:
var m = new Map(); // 空Map
m.set('Adam', 67); // 添加新的key-value
m.set('Bob', 59);
m.has('Adam'); // 是否存在key 'Adam': true
m.get('Adam'); // 67
m.delete('Adam'); // 删除key 'Adam'
m.get('Adam'); // undefined
Map的forEach()回调函数参数依次为value、key和map本身:
var m = new Map([[1, 'x'], [2, 'y'], [3, 'z']]);
m.forEach(function (value, key, map) {
alert(value);
});
(2)Set
Set和Map类似,也是一组key的集合,但不存储value。
var s1 = new Set(); // 空Set
var s2 = new Set([1, 2, 3]); // 含1, 2, 3
Set具有以下方法:
s2.add(4);//1,2,3,4
s2.delete(3);//1,2,4
(3)iterable
ES6标准引入了新的iterable类型,Array、Map和Set都属于iterable类型。
具有iterable类型的集合可以通过新的for ... of循环来遍历:
var a = ['A', 'B', 'C'];
var s = new Set(['A', 'B', 'C']);
var m = new Map([[1, 'x'], [2, 'y'], [3, 'z']]);
for (var x of a) { // 遍历Array
alert(x);
}
for (var x of s) { // 遍历Set
alert(x);
}
for (var x of m) { // 遍历Map
alert(x[0] + '=' + x[1]);
}
Set与Array类似,但Set没有索引,因此forEach()回调函数的前两个参数都是元素本身:
var s = new Set(['A', 'B', 'C']);
s.forEach(function (element, sameElement, set) {
alert(element);
});
3.函数
ES6标准引入了rest参数,如下:
function foo(a, b, ...rest) {
console.log('a = ' + a);
console.log('b = ' + b);
console.log(rest);
}
foo(1, 2, 3, 4, 5);
// 结果:
// a = 1
// b = 2
// Array [ 3, 4, 5 ]
foo(1);
// 结果:
// a = 1
// b = undefined
// Array []
注意:rest参数只能写在最后,前面用...标识。
4.高阶函数
一个函数可以接收另一个函数作为参数,这种函数就称之为高阶函数。
function add(x, y, f) {
return f(x) + f(y);
}
5.箭头函数
ES6标准新增了一种新的函数:Arrow Function(箭头函数)。
箭头函数相当于匿名函数,简化了函数定义。
箭头函数有两种格式:
(1)一种只包含一个表达式:x => x * x
(2)一种可以包含多条语句,不能省略{ ... }和return:
x => {
if (x > 0) {
return x * x;
}
else {
return - x * x;
}
}
注:多个参数用括号()括起来。箭头函数还有一个作用,完全修复了this的指向,this总是指向词法作用域,也就是外层调用者obj:
var obj = {
birth: 1990,
getAge: function () {
var b = this.birth; // 1990
var fn = function () {
return new Date().getFullYear() - this.birth; // this指向window或undefined
};
return fn();
}
var obj = {
birth: 1990,
getAge: function () {
var b = this.birth; // 1990
var fn = () => new Date().getFullYear() - this.birth; // this指向obj对象
return fn();
}
};
obj.getAge(); // 25
};
6.generator
generator(生成器)是ES6标准引入的新的数据类型。
generator跟函数很像,定义如下:
function* foo(x) {
yield x + 1;
yield x + 2;
return x + 3;
}
generator和函数不同的是,generator由function*定义(注意多出的*号),并且除了return语句,还可以用yield返回多次。
function* fib(max) {
var
t,
a = 0,
b = 1,
n = 1;
while (n < max) {
yield a;
t = a + b;
a = b;
b = t;
n ++;
}
return a;
}
调用generator对象方法是不断地调用generator对象的next()方法:var f = fib(5);
f.next(); // {value: 0, done: false}
f.next(); // {value: 1, done: false}
f.next(); // {value: 1, done: false}
f.next(); // {value: 2, done: false}
f.next(); // {value: 3, done: true}
7.promise对象
“承诺将来会执行”的对象在JavaScript中称为Promise对象。
function test(resolve, reject) {
var timeOut = Math.random() * 2;
log('set timeout to: ' + timeOut + ' seconds.');
setTimeout(function () {
if (timeOut < 1) {
log('call resolve()...');
resolve('200 OK');
}
else {
log('call reject()...');
reject('timeout in ' + timeOut + ' seconds.');
}
}, timeOut * 1000);
}
var p1 = new Promise(test);
var p2 = p1.then(function (result) {
console.log('成功:' + result);
});
var p3 = p2.catch(function (reason) {
console.log('失败:' + reason);
});
//Promise对象可以串联起来
new Promise(test).then(function (result) {
console.log('成功:' + result);
}).catch(function (reason) {
console.log('失败:' + reason);
});
//Promise可以执行若干个异步任务,比如需要先做任务1,如果成功后再做任务2,任何任务失败则不再继续并执行错误处理函数。
job1.then(job2).then(job3).catch(handleError);
//两个任务需要并行执行的,用Promise.all()
// 同时执行p1和p2,并在它们都完成后执行then:
Promise.all([p1, p2]).then(function (results) {
console.log(results); // 获得一个Array: ['P1', 'P2']
});
//多个异步任务只需要获得先返回的结果时,用Promise.race()实现
Promise.race([p1, p2]).then(function (result) {
console.log(result); // 'P1'
});