2019.5.27开始 2019.6.2结束 于2019.6.3 整理
目录
1.let const:
2.箭头函数
3.函数的扩展
4.解构赋值
5.数组
6.字符串
7.正则扩展
8.对象扩展
9.面向对象
10.JOSN
11.Symbol
12.Set、Map
1.Set
weakSet
2.Map
WeakMap
13.Proxy和Reflect
14.Promise
15.Iternator迭代器和for..of循环
16.Generator函数
17.async
JS中-----var:
1.可以重复声明
2.无法限制修改
3.没有块级作用域
ES6:-----------let 变量 / const 常量(不可修改read only )
1.不可重复声明
2.块级作用域
3.声明时必须赋值
传统:function(){ }
es6: ()=>{ }
去function 变 =>
作用:简化回调函数
1.如果只有一个参数,()可以省
2.如果只有一个return , { }和return 可以一起省
3.如果箭头函数返回一个对象,必须在对象外面加上括号
注意:
1.函数体内的this对象就是定义时所在的对象(固定),而不是使用时所在的对象
this指向的固定化是因为箭头函数并没有自己的this,导致内部的this就是外层代码块的this。正因为它没有this对象,也就不可以当做构造函数。也不能使用bind(),apply(),call()方法。
2.不可以当做构造函数(不可以使用new 命令)
3.不可以使用argements对象(可用test参数代替)
4.不可以使用yield命令,因此箭头函数不可用作Generator函数
rest参数
rest参数(形式为“...变量名”),用于获取函数的多余参数
function show(a,b,...args){}
rest参数必须为最后一个,否则会报错
函数的length属性不包括rest参数
扩展运算符
扩展运算符是三个点(...)。
好比rest参数的逆运算,将一个数组转为用逗号分隔的参数序列。
console.log(...[1,2,3])//1,2,3
扩展运算符的应用:
1.合并数组
[...arr1,...arr2,...arr3]
2.与解析赋值结合生成数组
3.函数可返回多个值
4.将字符串转为数组
5.可将类似数组的对象转为真正的数组
6.Map、Set结构,Generator函数
默认参数
直接写在函数定义的后面
参数变量默认声明,因此不能用let 或者const再次声明
默认参数的位置:
默认值的参数应该是函数的尾参数。如果非尾部的参数设置默认值,该参数无法省略。
function f(x=1,y){ return [x,y]; } f() //[1,undefined] f(2)//[2,undefined] f(, 1)//报错 f(underfined,1) //[1,1]
上述代码中,默认值的参数并不是函数的尾参数,因此该参数不可省略,可显式输入undefined。如果传入undefined,将触发该参数等于默认值,null则没有该效果。
函数的length属性:
指定默认值后,函数的length属性为没有指定默认值的参数个数。
length属性的含义是该函数预期传入的参数个数。某个参数指定默认值以后,预期传入的参数个数就不包括这个参数了。
作用域:
先是当前函数的作用域,再是全局作用域
name的属性:
返回该函数的函数名
如果将一个匿名函数的对象赋值给一个变量,会返回实际的函数名(ES5中返回空字符串)
Function构造函数返回的函数实例,name的属性值为"annoymous"
bind返回的函数,name属性值会加上“bound”前缀
function foo(){}; foo.bind({}).name //"bound foo" (function(){}).bind({}).name //"bound"
解构:按照一定模式,对变量进行赋值
1.左右两边解构一致(按照位置的对应关系对变量赋值)
2.右边必须是个东西(数组、对象、Map、Set)
3.声明和赋值不能分开(必须在一句话里完成)
解构赋值适用于var let const命令
不完全解构:等号左边的模式只匹配右边的一部分
只要某种数据结构具有Iterator接口,都可以结构赋值
解构赋值允许指定默认值
对象的解构赋值与数组的区别
数组的元素按次序排列,变量的取值由位置决定;
对象的属性没有次序,变量必须与属性同名,才能取到正确值。
对象的解构赋值的内部机制是:先找到同名属性,再赋值给对应的变量。真正被赋值的是后者。
圆括号问题
以下三种解构赋值不得使用圆括号:
1.变量声明语句(var / let / const...)
2.函数参数
3.不能将整个模式或嵌套模式的一层放在圆括号中
可以使用圆括号的情况:赋值语句的非模式部分
解构赋值的用途
1.交换变量的值
2.从函数返回多个值
3.函数参数的定义
4.提取JSON数据
5.遍历Map结构
6.输入模块的指定方法
map 映射(一个对一个)
reduce 汇总(一堆对一个)
filter 过滤器
forEach 循环(迭代)
1.新方法:
startsWith()/endsWith() 以...开头或者结尾
2.字符串模板:(字符串的连接)
反单引号``
直接把东西放入字符串 ${东西}
可以折行
y修饰符:
g修饰符类似,也是全局匹配,后一次匹配都从上一次匹配成功的下一个位置开始。
不同之处在于,g修饰符只要剩余位置中存在匹配就可,而y修饰符确保匹配必须从剩余的第一个位置开始,这也就是“粘连”的涵义。
var s = 'aaa_aa_a';
var r1 = /a+/g;
var r2 = /a+/y;
console.log(r1.exec(s));//["aaa"]
console.log(r2.exec(s));//["aaa"]
console.log(r1.exec(s));//["aa"]
console.log(r2.exec(s));//null
//判断是否是y修饰符
console.log(r1.sticky,r2.sticky);//false true
u修饰符:
会正确处理四个字节的UTF-16编码。
ES5则不支持四个字节的UTF-16编码,会将其识别为两个字符。
console.log('u-1',/^\uD83D/.test('\uD83D\uDC2A'));//true
console.log('u-2',/^\uD83D/u.test('\uD83D\uDC2A'));//false
点(.)字符在正则表达式中,含义是除了换行符以外的任意单个字符。
对于码点大于0xFFFF的 Unicode 字符,点字符不能识别,必须加上u修饰符。
var r = '?'; console.log('u',/^.$/.test(r));//false
console.log('u-0',/^.$/u.test(r));//true
函数新增特性:
简洁表示法
属性和方法都可以简写
属性表示法
扩展运算符
Object新增方法
1.Object.is();
//ES5:
console.log(+0===-0);//true
console.log(NaN===NaN)//false
//ES6:
console.log(Object.is(+0,-0));//false
console.log(Object.is(NaN,NaN));//true
2.Object.assign()
Object.assign方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)。第一个参数是目标对象,后面的参数都是源对象。
Object.assign拷贝的属性是有限制的,只拷贝源对象的自身属性。不拷贝继承属性,也不拷贝不可枚举的属性(enumerable: false)。
只有字符串的包装对象,才会会产生可枚举属性。
const v1='abc'; const v2=true; const v3=10; const obj=Object.assign({},v1,v2,v3); //只有字符串合入目标对象(以字符数组的形式),数值和布尔值都会被忽略 console.log(obj);//{0: "a", 1: "b", 2: "c"}
注意:
1.浅拷贝
2.同名属性会进行覆盖
3.可用来处理数组,会把数组当做对象
Object.assign([1, 2, 3], [4, 5])// [4, 5, 3]
3.Object.keys()---键名
Object.values()---键值
Object.entries()---键值对
Object.fromEntries()--将键值对数组转化为对象
1.class关键字、构造器和类分开
2.class里面直接加方法
function Point(x,y){
this.x=x;
this.y=y;
}
Point.prototype.toString=function(){
return'('+this.x+','+this.y+')';
}
||
//定义类
class Point(){
//构造方法:
constructor(x,y){
this.x=x;
this.y=y;
}
toString(){
return'('+this.x+','+this.y+')';
}
}
继承:通过extends关键字实现
class ColorPoint extends Point{
constructor(x,y,color){
super(x,y);//调用父类constructor(x,y)
this.color=color;
}
toString(){
return this.color+''+super.toString();
}
}
json的标准写法:
1.只能用双引号
2.所有的名字(key)都得用双引号包起来
简写:
1.key value一样时可以只写一个;
let a=21;
let b=5;
let json2={a:a,b:b};
console.log(json2);//{a: 21, b: 5}
//可简写如下:
let json3={a,b,c:74};
console.log(json3);//{a: 21, b: 5, c: 74}
2.函数里面的方法" :function "可省略
let json4={
a:12,
show:function(){
console.log(this.a);
}
};
json4.show();//12
//可简写如下:
let json5={
a:12,
show(){
console.log(this.a);
}
};
json5.show();//12
JS数据类型:
字符串(String)、数值(Number)、布尔值(Boolean)、undefined、null、对象(Object)。
Symbol为JS中第七种数据类型,用来保证每个属性名都是独一无二的
对象的属性名的两种类型:原有字符串、Symbol类型
1.Symbol.protoytpe.descriptioon
用来返回Symbol的描述
const sym=Symbol('foo'); console.log(sym.description);//foo
2.Object.getOwnPropertySymbols()
用来遍历属性名,获取指定对象的所有Symbol的属性名
可拿到Symbol和非Symbol的属性
const obj = {};
let foo = Symbol("foo");
Object.defineProperty(obj, foo, {
value: "foobar"
});
for (let i in obj) {
console.log(i); // 无输出
}
console.log(Object.getOwnPropertyNames(obj));// []
console.log(Object.getOwnPropertySymbols(obj));// [Symbol(foo)]
3.Symbol.for()、Symbol.keyFor()
共同点:都会生成新的Symbol
区别:
Symbol.for()会先检查给定的key是否存在,若不存在才会新建。
Symbol()在每次调用都会产生一个新的Symbol
类似数组,成员值唯一
返回长度:size
Set元素不可重复(可用来去重)
转换元素的时候不会做数据类型的转换
Set 实例的方法分为两大类:操作方法(用于操作数据)和遍历方法(用于遍历成员)。
操作方法
add(value):添加某个值,返回 Set 结构本身。
delete(value):删除某个值,返回一个布尔值,表示删除是否成功。
has(value):返回一个布尔值,表示该值是否为Set的成员。
clear():清除所有成员,没有返回值。
遍历方法
keys():返回键名的遍历器
values():返回键值的遍历器
entries():返回键值对的遍历器
forEach():使用回调函数遍历每个成员
与Set区别:
1.WeakSet 的成员只能是对象,而不能是其他类型的值。
2.WeakSet 中的对象都是弱引用,即垃圾回收机制不考虑 WeakSet 对该对象的引用,也就是说,如果其他对象都不再引用该对象,那么垃圾回收机制会自动回收该对象所占用的内存,不考虑该对象还存在于 WeakSet 之中。
类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。
Map 结构的实例有以下属性和操作方法。
(1)size 属性:返回 Map 结构的成员总数。
(2)set(key, value):set方法设置键名key对应的键值为value,然后返回整个 Map 结构。如果key已经有值,则键值会被更新,否则就新生成该键。
(3)get(key):get方法读取key对应的键值,如果找不到key,返回undefined。
(4)has(key):has方法返回一个布尔值,表示某个键是否在当前 Map 对象之中。
(5)delete(key):delete方法删除某个键,返回true。如果删除失败,返回false。
(6)clear():clear方法清除所有成员,没有返回值。
WeakMap的专用场合就是,它的键所对应的对象,可能会在将来消失。WeakMap结构有助于防止内存泄漏。
注意,WeakMap 弱引用的只是键名,而不是键值。键值依然是正常引用。
Proxy
--修改某些操作的默认行为
注意:要使得Proxy起作用,必须针对Proxy实例进行操作,而不是针对目标对象进行操作。
var proxy = new Proxy(target, handler);
target参数:要拦截的目标对象
handler参数:也是一个对象,用来定制拦截行为(拦截处理函数)。
Reflect对象的方法与Proxy对象的方法一一对应,只要是Proxy对象的方法,就能在Reflect对象上找到对应的方法。
同步与异步
"异步",简单说就是一个任务不是连续完成的,可以理解成该任务被人为分成两段,先执行第一段,然后转而执行其他任务,等做好了准备,再回过头执行第二段。
连续的执行就叫做同步。由于是连续执行,不能插入其他任务,所以操作系统从硬盘读取文件的这段时间,程序只能一直等着。
1.含义
Promise 是异步编程的一种解决方案,是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。
从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。
有三种状态:Pending(进行中)、Resolved(已完成)、Rejected(已失败)
状态改变:
进行中--->已完成
进行中--->已失败
特点:
(1)对象的状态不受外界影响;
(2)一旦状态改变,就不会再变,任何时候都可以得到这个结果;
(3)Promise对象提供统一的接口,使得控制异步操作更加容易。
缺点:
(1)无法取消Promise,一旦新建它就会立即执行,无法中途取消。
(2)如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。
(3)当处于pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。
2.基本用法
resolve函数:将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;
reject函数:将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数。
then方法可以接受两个回调函数作为参数。(then方法将会在当前脚本所有同步任务执行完才执行)
第一个回调函数是Promise对象的状态变为resolved时调用;(必选)
第二个回调函数是Promise对象的状态变为rejected时调用。(可选)
function timeout(ms){ return new Promise(function (resolve,reject){ setTimeout(resolve,ms,'done'); }) } timeout(100).then(function (value){ console.log(value);//done });
Promise.prototype.then()
作用:
为Promise添加状态改变时的回调函数
参数:
参数一:Resolved状态的回调函数
参数二:(可选)Reject状态的回调函数
Promise.prototype.catch()
指定发生错误的回调函数(处理前一个函数运行时发生的错误)
Promise.all()、Promise.race()
多个Promise实例包装成一个新的Promise实例
var p=Promise.all([p1,p2,p3]); var p=Promise.race([p1,p2,p3])
注意:
在Promise.all方法中,只有p1,p2,p3状态都改变,p的状态才改变;
而Promse.race中,只要有一个状态改变,p就改变。
概念
遍历器(Iterator)是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作。
原生具备 原生具备 Iterator 接口的数据结构如下:
Array Map Set String TypedArray 函数的 arguments 对象 NodeList 对象
作用
一是为各种数据结构,提供一个统一的、简便的访问接口;
二是使得数据结构的成员能够按某种次序排列;
三是 ES6 创造了一种新的遍历命令for...of循环,Iterator 接口主要供for...of消费。
基本概念:
1.状态机,封装了多个内部状态
2.会返回一个遍历器对象
特征:
1.function 函数与函数名之间有一个 *
2.函数体内部使用yield定义不同的内部状态
注意:
1.任意一个对象的Symbol.iterator方法等于该对象的遍历器对象生成函数,调用该函数会返回该对象的一个遍历器对象
function *gen()
{
}
var g = gen();
console.log(g[Symbol.iterator]() === g);//true
2.yield后面的表达式只有调用next()或者内部指针指向该语句时才会执行。
//1.调用next()
function *f()
{
yield 1;
yield 2;
yield 3;
}
var g=f();
console.log(g.next());//{value: 1, done: false}
console.log(g.next());//{value: 2, done: false}
console.log(g.next());//{value: 3, done: false}
console.log(g.next());//{value: undefined, done: true}
//for..od遍历
let obj={};
obj[Symbol.iterator]=function* (){
yield 1;
yield 2;
yield 3;
}
for(let value of obj){
console.log(value);
//1
//2
//3
}
//简写:for..of会自动遍历Generator对象
function*foo()
{
yield 1;
yield 2;
yield 3;
}
for(let v of foo()){
console.log(v);
//1
//2
//3
}
案例1:
模拟抽奖
let draw = function (count) {
alert(`剩余${count}次`);
}
let residue = function * (count)
{
while (count > 0) {
count--;
yield draw(count);
}
}
let star = residue(5);
let btn = document.createElement('button');
btn.id = 'start';
// btn.textContent='抽奖';
btn.innerText = '抽奖';
document.body.appendChild(btn);
document.getElementById('start').addEventListener('click', function () {
star.next();
}, false);
案例2:
长轮询
// 模拟AJAX过程
let ajax=function* (){
yield new Promise(function(resolve,reject){
setTimeout(function(){
resolve({code:0})
},200);
})
}
let pull=function(){
let generator=ajax();
let step=generator.next();
step.value.then(function(d){
if(d.code!=0){
setTimeout(function(){
console.log('wait');
pull();
},1000);
}else{
console.info(d);
}
})
}
pull();
它是 Generator 函数的语法糖。
async函数对 Generator 函数的改进,体现在以下四点。
(1)内置执行器。
Generator 函数的执行必须靠执行器,所以才有了co模块,而async函数自带执行器。也就是说,async函数的执行,与普通函数一模一样,只要一行。
asyncReadFile();
上面的代码调用了asyncReadFile函数,然后它就会自动执行,输出最后结果。这完全不像 Generator 函数,需要调用next方法,或者用co模块,才能真正执行,得到最后结果。
(2)更好的语义。
async和await,比起星号和yield,语义更清楚。async表示函数里有异步操作,await表示紧跟在后面的表达式需要等待结果。
(3)更广的适用性。
co模块约定,yield命令后面只能是 Thunk 函数或 Promise 对象,而async函数的await命令后面,可以是 Promise 对象和原始类型的值(数值、字符串和布尔值,但这时会自动转成立即 resolved 的 Promise 对象)。
(4)返回值是 Promise。
async函数的返回值是 Promise 对象,这比 Generator 函数的返回值是 Iterator 对象方便多了。你可以用then方法指定下一步的操作。
进一步说,async函数完全可以看作多个异步操作,包装成的一个 Promise 对象,而await命令就是内部then命令的语法糖。
18.修饰器(Decorator)
修饰器函数,用来修改类的行为
修饰器只能用于类和类的方法,不能用于函数,因为存在函数提升。
19.模块化
ES6 模块的设计思想是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。
ES6 模块不是对象,而是通过export命令显式指定输出的代码,再通过import命令输入。
ES6 的模块自动采用严格模式,严格模式主要有以下限制:
export:使用export命令定义了模块的对外接口
// profile.js
var firstName = 'Michael';
var lastName = 'Jackson';
var year = 1958;
export { firstName, lastName, year };
import:用于输入其他模块提供的功能。
// main.js
import { firstName, lastName, year } from './profile.js';
function setName(element) {
element.textContent = firstName + ' ' + lastName;
}