1、let、var、const
let申明的变量只在其所在的代码块有效(适合申明代码块内的变量,代码块外注销,ex:for循环计数器)
ES6 明确规定,如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。
const声明不能被重新赋值,但引用类型的值时指针不变的情况下可以正常修改起属性值(Object.freeze()禁止修改属性值)
立即执行函数(变量私有化):IIFE: Immediately Invoked Function Expression
(function(){声明变量})<=>{const 变量}
变量提升:var:undefine let(临时性死区):err
ES6 的块级作用域必须有大括号
ex:
var a = 2;
{
let a = 3;
console.log(a); // 3
}
console.log(a); // 2
// const->let->var
2、箭头函数
隐式返回;函数中 this 总是绑定总是指向对象自身:()=>{}
function Person(){
this.age = 0;
setInterval(() => {
// |this| 指向 person 对象
this.age++;
}, 1000);
}
var person = new Person();
- 注1:不适合箭头函数的情况:
通常this会指定为Windows对象
(1)作为构造函数,一个方法需要绑定到对象
(2)绑定到指定对象:交互事件/绑定指定元素等
(3)需要使用argument对象
- 注2:
(1)函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。
(2)不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。
(3)不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。
(4)不可以使用yield命令,因此箭头函数不能用作 Generator 函数。
3、函数默认值
function(a=2,b=3){}
与解构赋值默认值结合
function foo({x, y = 5}) {
console.log(x, y);
}
foo({}) // undefined 5
foo({x: 1}) // 1 5
foo({x: 1, y: 2}) // 1 2
foo() // TypeError: Cannot read property 'x' of undefined
4、模板字符串
const sentence = '${变量} is ${变量} years old'
=>
${变量}
处理用户输入,净化非法输入内容
5、新增的字符串函数
// index位置,大小写敏感
- .startsWith(string,index)
- .endsWith(string,index)
- .includes(string,index)<=>.indexOf() !== -1
- .repeat(n)重复次数
- .join()数组取消逗号;
- .trim()字符串取消空格;
- .padStart()/.panEnd()补全长度
6、函数的扩展
rest 参数(形式为...变量名)获取函数的多余参数,可代替arguments对象使用
// arguments(类数组)变量的写法
//Array.prototype.slice.call将其转为数组
function sortNumbers() {
return Array.prototype.slice.call(arguments).sort();
}
// rest参数的写法
const sortNumbers = (...numbers) => numbers.sort();
7、Symbol
ES6 引入了一种新的原始数据类型Symbol,表示独一无二的值,可以转换为字符串、布尔值,不能转换为数值
let s = Symbol('foo');//接受一个描述参数
typeof s
// "symbol"
s.description // "foo"
8、Set和Map
Set结构不会添加重复元素(可用于去重)
const s = new Set();
[2, 3, 5, 4, 5, 2, 2].forEach(x => s.add(x));
for (let i of s) {
console.log(i);
}
// 2 3 5 4
// 去除数组的重复成员
[...new Set(array)]
//去除字符串里面的重复字符
[...new Set('ababbc')].join('')
// "abc"
9、Promise(和Stream)
Promise 是异步编程的一个构造函数
三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)
const promise = new Promise(function(resolve, reject) {
// ... some code
//1、判断
if (/* 异步操作成功 */){
resolve(value);
} else {
reject(error);
}
});
//2、回调
promise.then(function(value) {
// success
}, function(error) {
// failure
});
如果调用resolve函数和reject函数时带有参数,那么它们的参数会被传递给回调函数。reject函数的参数通常是Error对象的实例,表示抛出的错误;resolve函数的参数除了正常的值以外,还可能是另一个 Promise 实例
const p1 = new Promise(function (resolve, reject) {
// ...
});
const p2 = new Promise(function (resolve, reject) {
// ...
resolve(p1);
})
- Promise.prototype.then():添加状态改变时的回调函数;
- Promise.prototype.catch():指定发生错误时的回调函数
- Promise.try():让同步函数同步执行,异步函数异步执行
(1)async
//f是同步的时候
const f = () => console.log('now');
(async () => f())();// 立即执行函数
console.log('next');
// now
// next
// f是异步时
(async () => f())()
.then(...)//异步执行下一步操作
.catch(...)//捕获错误
(2)new Promise()
const f = () => console.log('now');
(
() => new Promise(
resolve => resolve(f())
)
)();
console.log('next');
// now
// next
//上述写法等价于
const f = () => console.log('now');
Promise.try(f)
.then(...)
.catch(...)
console.log('next');
// now
// next
注:Promise.try就是模拟try代码块,就像promise.catch模拟的是catch代码块
10、Generator
语法上,首先可以把它理解成,Generator 函数是一个状态机,封装了多个内部状态
形式上,Generator 函数是一个普通函数,但是有两个特征。
- function关键字与函数名之间有一个星号;
- 函数体内部使用yield表达式,定义不同的内部状态(yield在英语里的意思就是“产出”)。
function* helloWorldGenerator() {
yield 'hello';
yield 'world';
return 'ending';
}
var hw = helloWorldGenerator();
hw.next()
// { value: 'hello', done: false }
hw.next()
// { value: 'world', done: false }
hw.next()
// { value: 'ending', done: true }
hw.next()
// { value: undefined, done: true }
//value属性表示当前的内部状态的值,是yield表达式后面那个表达式的值;
//done属性是一个布尔值,表示是否遍历结束。
和Iterator结合使用:
var myIterable = {};
myIterable[Symbol.iterator] = function* () {
yield 1;
yield 2;
yield 3;
};
[...myIterable] // [1, 2, 3]
- 函数的异步应用实现:
a1(astart)——b——a2(aend)
(1)回调函数
fs.readFile('/etc/passwd', 'utf-8', function (err, data) {
if (err) throw err;
console.log(data);
});
//返回/etc/passwd之后开始执行function
(2)Promise
解决多个回调函数嵌套会造成“回调函数地狱”,新的写法
var readFile = require('fs-readfile-promise');
readFile(fileA)
.then(function (data) {
console.log(data.toString());
})
.then(function () {
return readFile(fileB);
})
.then(function (data) {
console.log(data.toString());
})
.catch(function (err) {
console.log(err);
});
(3)Generator
a、协程写法:
function* asyncJob() {
// ...其他代码
var f = yield readFile(fileA);
// ...其他代码
}
//函数asyncJob是一个协程.yield命令表示执行到此处,执行权将交给其他协程
可等价于async:
function async asyncJob() {
// ...其他代码
var f = await readFile(fileA);
// ...其他代码
}
asyncReadFile();
b、协程的Generator函数实现:
function* gen(x) {
try {
var y = yield x + 2;
} catch (e){
console.log(e);
}
return y;
}
var g = gen(1);
g.next() // { value: 3, done: false }
g.next() // { value: undefined, done: true }
g.next(2) // { value: 2, done: true }
g.throw('出错了'); // 出错了
// next接受一个参数,作为上个阶段异步任务的返回结果,被函数体内的变量y接收
- 缺点:流程管理却不方便(即何时执行第一阶段、何时执行第二阶段)。
(4)Thunk函数(自动执行 Generator 函数的一种方法)// 不太懂
传值调用和传名调用的区分中将参数放到一个临时函数之中,再将这个临时函数传入函数体。这个临时函数就叫做 Thunk 函数。
JavaScript 语言是传值调用,它的 Thunk 函数含义有所不同。在 JavaScript 语言中,Thunk 函数替换的不是表达式,而是多参数函数,将其替换成一个只接受回调函数作为参数的单参数函数
function f(a, cb) {
cb(a);
}
const ft = Thunk(f);
ft(1)(console.log) // 1
基于Promise对象的自动执行,co模块(一个小插件),难奥