let和const会创建块级作用域
尾调用
字符串模板 标签模板
数组的解构赋值
{
let [a,b]=[1,2]
console.log(a,b) // 1 2
}
{
let [a,b,c=3]=[1,2] // 默认值 没有则为undefined
console.log(a,b) // 1 2 3
}
{
let a=1,b=2;
[a,b]=[b,a]; //变量的交换
console.log(a,b) // 2 1
}
{
function f() {
return [1, 2]
}
let a, b;
[a, b] = f();
console.log(a, b) // 1 2
}
{
function f() {
return [1, 2, 3, 4, 5, 6, 7]
}
let a, b, rest;
[a, , , b] = f();
console.log(a, b) // 1 4
}
{
function f() {
return [1, 2, 3, 4, 5, 6, 7]
}
let a, b, rest;
[a, b, ...rest] = f();
console.log(a, b, rest) // 1 2 [3,4,5,6,7]
}
{
let [a,b,...rest]=[1,2,3,4,5,6,7]
console.log(a,b,rest) // 1 2 [3, 4, 5, 6, 7]
}
对象的解构赋值
{
let a,b;
({a,b}={a:1,b:2})
console.log(a,b) // 1 2
}
{
let o={p:42,b:true};
let {p,b}=o;
console.log(p,b) // 42 true
}
{
let o={a:1,b:2};
let p,b;
({p=10,b=10}={p:1}); // 默认值
console.log(p,b) // 1 10
}
{
let meta={
data:'abc',
test:[{
data:'data',
desc:'desc'
}]
}
let {data:adata,test:[{data:bdata}]}=meta
console.log(adata,bdata) // abc data
}
字符串拓展
{
let a=?;
console.log(a.codePointAt(0)) // 134071
console.log (a.codePointAt(0).tostring(16)) //20bb7 获取大于两个字节的字符的码值
console.log(String.fromCodePoint("0x20bb7")) // ? 通过码值取字符
}
{
let str='string';
let arr=[1,2,3,4,NaN];
arr.includes("NaN"); //true 在数组中寻找指定值,包括NaN
str.includes("c"); //查询字符串是否包含字符"c"
str.startsWith("str"); //是否以"str"为开头
str.endsWith("ing"); //是否以"ing"结束
str.repeat(2) // 重复两次
}
{
let str='1';
console.log(str.padStart(2,'0')) //如果str不够2位数,在开头用‘0’ 补白 ES7提案
console.log(str.padEnd(3,'0')) // 如果str不够3位数,在末尾用‘0’ 补白 ES7提案
}
{
console.log(String.raw`Hi\n${1+2}`) // Hi\n3 对所有"\"进行转义 换行符不生效
console.log(`Hi/\n${1+2}`) // Hi (换行)3
}
数组拓展
{
console.log( 0b111110111 ); //503 0b 表示二进制数 字母b大小写都可以
console.log( 0o767 ); //503 0b 表示八进制数
}
{
Number.isFinite(15) //判断一个数是否为有尽 就是有效数字
Number.isNaN(1) //判断一个数是否是NaN 也就是不是数字
}
{
Number.isInteger(1) //true 判断一个数是否为整数
Number.isInteger(1.0) //true
Number.isInteger(1.1) //false
Number.isInteger('1') //false
}
{
Number.MAX_SAFE_INTEGER 2的53次方 一个有效数的最大范围
Number.MIN_SAFE_INTEGER -2的53次方 一个有效数的最小范围
Number.isSafeInteger(10) //判断一个数是否在安全范围 即是否有效
}
{
Math.trunc(4.1) //获取一个数的整数部分
}
{
Math.sign(-5) //-1 判断一个数是正数,负数,还是0
Math.sign(0) //0
Math.sign(5) //1
}
{
Math.cbrt(-1) //-1 求立方根
Math.cbrt(9) //3
}
{
Array.of() //创建一个空数组
Array.of(1,2,3,4,5) //创建数组[1,2,3,4,5]
}
{
<p>es6</p>
<p>慕课</p>
<p>java</p>
<script>
let p=document.getElementsByTagName('p');
let pArr=Array.from(p); //将一个集合转换为数组
pArr.forEach(function(item){
console.log(item.textContent)
})
</script>
Array.from([1,2,3],(item)=>item*2) //有第二个参数的时候 ,相当于一个map功能,将数组里的值跑了一遍
}
{
let arr=Array.of(1,2,3,4,5,6,7);
console.log(arr.fill('a')) //["a", "a", "a", "a", "a", "a", "a"] 将数组里的值全部替换成‘a’
console.log(arr.fill('a',1,3)) //[1, "a", "a", 4, 5, 6, 7] 将数组里下标为1-3的值(不包括第三个)替换成‘a’
}
{
let arr=Array.of('a','b','c'); for(let key of arr.keys()){ //遍历数组的索引 console.log(index) } for(let value of arr.values()){ //遍历数组的值 console.log(value) } for(let [key,value] of arr.entries()){ //遍历数组的索引和值 console.log(index,value) }
}
{
let arr=Array.of(1,2,3,4,5,6,7);
console.log(arr) // [1, 2, 3, 4, 5, 6, 7]
console.log(arr.copyWithin(0,4,6)) // [5, 6, 3, 4, 5, 6, 7] 从第0个开始替换,换成第四个到第六个的值(不包括第六个)
}
{
let arr=Array.of(1,2,3,4,5,6,7);
console.log(arr.find((item)=>item>3)) //在数组中找到大于3的数,找到就停止
console.log(arr.findIndex((item)=>item>3)) //在数组中找到大于3的数的索引值,找到就停止
}
函数拓展
{
function dem(a,b='world'){ //函数默认值 有默认值的参数后面的参数,必须也有默认值
console.log(a,b)
}
dem('hello')
}
{
function dem(...res){ //将传入的参数转成一个数组res res参数之后 不能再有别的参数
for(var i of rest){
console.log(i)
}
}
dem(1,2,3,4,5,6) // 1 2 3 4 5 6
}
{
console.log(...[1,2,4]) // 1 2 4 将数组转为离散的值
console.log('a',...[1,2,4]) // a 1 2 4
}
{
let arrow = v => v*2; // 箭头函数 实际为 let arrow = ( v ) =>{ v*2 } 当参数只有一个时,括号可以省略,当函数直接return时,花括号可以省略
arrow(6); // 12
}
对象拓展
{
let o=1,k=2;
let es5={
o:o,
k:k
}
let es6={ //简洁表示法
o,
k
}
console.log(es5,es6) // {o: 1, k: 2} {o: 1, k: 2}
let es5_method={
hello:function(){
console.log(1)
}
}
let es6_method={
hello(){ // 简洁表示法
console.log(1)
}
}
es5_method.hello() // 1
es6_method.hello() // 1
}
{
let a='con';
let es5_obj={
a:'c'
}
let es6_obj={
[a]:'c' // 属性表达式 中括号包起来的是一个表达式,也可以是一个变量
}
console.log(es5_obj,es6_obj) // {a: "c"} {con: "c"}
}
{
Object.is('abc','abc') //true 判断两个值是否相等 object.of 和“===” 一样
Object.is( [],[] ) //false
Object.assign({a:'a'},{b:'b'}) //拷贝 将B对象拷贝到A对象上 浅拷贝 如果b对象中 有继承的属性,不拷贝。 也不拷贝b对象中 不可枚举的属性
}
{
let test={a:1,b:2}
for (let [index,value] of Object.entries(test)){ //遍历对象 keys和values同样适用
console.log(index,value)
}
}
{
let {a,b,...c} = { a:1,b:2,e:3,f:4} // 拓展运算符
console.log(a,b,c) // 1 2 {e: 3, f: 4}
}
{
let arr = [1, 2, 3];
let arr1 = [
'a', 'b', ...arr // 拓展运算符
]
console.log(arr1) // ["a", "b", 1, 2, 3]
}
Symbol
{
let a=Symbol(); // 使用Symbol声明出来的值永远不可能相等 唯一性
let b=Symbol();
console.log(a===b) // false
let a1=Symbol.for('abc'); //使用Symbol定义一个key值为“abc”的变量a1,后面再使用“abc”这个变量定义的时候,
let a2=Symbol.for('abc'); 会寻找前文,如果使用过这个key值注册过,会返回这个值,如果没有,会注册一个独一无二的值
console.log(a1===a2) // true
}
{
let a=Symbol.for('abc');
let obj={
[a]:'123', //对象中使用Symbol做key值,for-in和let-of 取不到Symbol作为key的这个键值对
abc:'456',
c:'789'
}
console.log(obj) // {abc: "456", c: "789", Symbol(abc): "123"}
let syms=Object.getOwnPropertySymbols(obj); // 可以取到Symbol作为key的这个键值对,储存为一个数组
syms.forEach(function(item){
console.log(obj[item]) //123
})
Reflect.ownKeys(obj).forEach(function(item){ //可以取到Symbol作为Key和非Symbol作为key的所有键值对
console.log(item) // abc c Symbol(abc)
})
}
Set
{
let list=new Set(); //Set的定义方式 相当于数组,集合中的元素不能重复
list.add(1); //Set集合增加元素的方式
list.add(2);
console.log(list.size) // 2 Set集合的长度
let arr=[1,2,3,4,5,6];
let list1=new Set(arr) // 第二种定义方式 在转换数组的时候,不做类型转换 比如去重的时候,1和‘1’ 是不相等的
console.log(list1.size)
}
{
let list=new Set();
list.add(1);
list.add(2);
list.add(1); //添加重复元素 不生效
console.log(list) //{1, 2}
}
{
let arr=['add','delete','clear','has'];
let list=new Set(arr);
console.log(list.has('add')) //true // 判断是否拥有
list.delete('add') // 删除
console.log(list) //{"delete", "clear", "has"}
list.clear() //清空
console.log(list) //{}
}
{
let arr=['add','delete','clear','has'];
let list=new Set(arr);
for (let [index,value] of list.entries()){ //Set的遍历 key和value值相同,可以直接省略entries
console.log(index,value)
}
list.forEach(function(item,index){
console.log(item,index) // key和value值相同
})
}
WeakSet
{
let weaksetList=new WeakSet(); // weakset的元素只能是对象 弱引用 没有size属性,没有clear方法 不能遍历
let arg={a:1,b:2};
weaksetList.add(arg)
console.log(weaksetList)
}
Map
{
let map=new Map(); //Map的基本定义方法 object的key是字符串或者symbol,map的key可以是任何数据类型,比如数组
let arr =['123'];
map.set(arr,456); //Map添加元素 添加key为['123'], 值为456的一个键值对
console.log(map.has('a')) //false //判断是否拥有key为“a”的值
console.log(map) //{Array(1) => 456}
console.log(map.get(arr))//456 获取key的值
}
{
let map=new Map([['a',123],['b',456]]); //第二种定义方式,括号内为一个数组,数组里面用数组分开多个元素
console.log(map) //{"a" => 123, "b" => 456}
console.log(map.size) // 2 获取长度
map.delete('a'); //删除某一项
console.log(map) //{"b" => 456}
map.clear() //清空
console.log(map) //{}
}
WeakMap
{
let weakmap=new WeakMap(); //weakmap接受的key 只能是对象 弱引用 没有size属性,没有clear方法 不能遍历
let o={a:1,b:2};
weakmap.set(o,123);
console.log(weakmap) //{{…} => 123}
console.log(weakmap.get(o)) //123
}
Proxy
{
let obj={
time:'2018-10-14',
name:'aaa',
_r:123
}
let monitor = new Proxy(obj,{ // 代理obj
get(target,key){ // 拦截对象属性的读取 target就是 obj key就是要查询的key
return target[key].replace('2018','2012')
},
set(target,key,value){ // 拦截对象属性的设置 target就是 obj key就是要设置的key value就是要设置的值
if(key==='name'){
target[key]=value
}else{
return target[key]
}
},
has(target,key){ //拦截in操作符
if (key==='name'){
return target[key]
}else{
return false
}
},
deleteProperty(target,key){ //拦截delete操作符
if(key.includes('_')){
delete target[key];
return true
}else{
return target[key]
}
},
ownKeys(target){ //拦截Object.keys,Objdect.getOwnPropertySymbols,Object.getOwnPropertyNames
return Object.keys(target).filter(item=>item!='time')
}
})
console.log(monitor.time) // 2012-10-14 查询
monitor.time='2015' //设置
console.log(monitor) //Proxy {time: "2018-10-14", name: "aaa", _r: 123}
monitor.name='bbb' //设置
console.log(monitor) //Proxy {time: "2018-10-14", name: "bbb", _r: 123}
console.log('name' in monitor) //true in操作符
console.log('time' in monitor) //false in操作符
delete monitor.name //delete操作符
console.log(monitor) //Proxy {time: "2018-10-14", name: "bbb", _r: 123}
delete monitor._r //delete操作符
console.log(monitor) //Proxy {time: "2018-10-14", name: "bbb"}
console.log(Object.keys(monitor)) // ["name", "_r"] //判断是否含有这个key
}
Reflect
{
let obj={
time:'2018-10-14',
name:'aaa',
_r:123
}
console.log(Reflect.get(obj,'time')) //2018-10-14 Prexy有的方法 Reflect都有
Reflect.set(obj,'name','aa')
console.log(obj) //{time: "2018-10-14", name: "aa", _r: 123}
console.log(Reflect.has(obj,'_r')) //true
}
类和继承
{
class Parent{ //创建一个类
constructor(name='aaa'){ //构造函数
this.name=name
}
}
let v_parent=new Parent('a');
console.log(v_parent.name) //a
}
{
class Parent{
constructor(name='morenzhi'){
this.name=name
}
}
class Child extends Parent{ //继承
}
let v_child=new Child()
console.log(v_child) //morenzhi
}
{
class Parent{
constructor(name='morenzhi'){
this.name=name
}
}
class Child extends Parent{ //继承
}
let v_child=new Child()
console.log(v_child) //morenzhi
}
{
class Parent{
constructor(name='morenzhi'){
this.name=name;
}
}
class Child extends Parent{
constructor(name='Child-moren'){
super(name) //带参数的继承 如果child还有自己的属性,要写在super之后 如果实例带参数,参数会覆盖默认值
this.age=18;
}
}
let v_child=new Child()
console.log(v_child) //Child {name: "Child-moren", age: 18}
}
{
class Parent{
constructor(name='morenzhi'){
this.name=name;
}
get aName(){ //getter和setter 后面的aName 是属性 不是函数
return 'mk-'+this.name
}
set aName(value){
this.name=value
}
}
let v=new Parent('xuJM');
console.log(v.aName) //mk-xuJM
v.aName='xu';
console.log(v.aName) //mk-xu
}
{
class Parent{
constructor(name='morenzhi'){
this.name=name;
}
static tell(){ //静态方法 只能通过类取调用
console.log('tell')
}
}
Parent.tell() //tell
Parent.type='test'; //静态属性,通过类去定义和调用
console.log(Parent.type) //test
}
Promise
{
let ajax=function(){
console.log('ajax执行')
return new Promise(function(resolve,reject){ //promise的实例 异步操作 resolve:要执行的下一步操作 reject:中断当前操作
setTimeout(function(){
resolve();
},1000)
})
}
ajax().then(function(){ //promise实例的方法 执行下一步
console.log('resolve执行')
},function(){}) //如果还有第二个函数,代表的是reject
}
{
let ajax=function(){
console.log('ajax执行')
return new Promise(function(resolve,reject){ //多步异步调用
setTimeout(function(){
resolve();
},1000)
})
}
ajax()
.then(function(){
console.log('setTimeout执行1')
return new Promise(function(resolve,reject){
setTimeout(function(){
resolve()
},1000)
})
})
.then(function(){
console.log('setTimeout执行2')
})
}
{
let ajax=function(num){
console.log('ajax执行')
return new Promise(function(resolve,reject){
if(num>5){
resolve()
}else{
throw new Error('出错了')
}
})
}
ajax(3).then(function(){
console.log(6);
}).catch(function(err){ //捕获错误
console.log(err)
})
}
{
function loadImg(src){
return new Promise((resolve,reject)=>{
let img = document.createElement('img');
img.src=src;
img.οnlοad=function(){
resolve(img) //这里传递的img,在then中可以获取到
}
img.οnerrοr=function(err){
reject(err)
}
})
}
function showImgs(imgs){
imgs.forEach(function(img){
document.body.appendChild(img)
})
}
Promise.all([ //all下面数组的多个Promis实例状态都改变之后 才会触发Promise.all 就是三张图片都加载完成之后
loadImg('1.jpg'),
loadImg('2.jpg'),
loadImg('3.jpg')
]).then(showImgs)
}
{
function loadImg(src){
return new Promise((resolve,reject)=>{
let img = document.createElement('img');
img.src=src;
img.οnlοad=function(){
resolve(img)
}
img.οnerrοr=function(err){
reject(err)
}
})
}
function showImgs(imgs){
let p=document.createElement('p');
p.appendChild(imgs);
document.body.appendChild(p)
}
Promise.race([ // 下面多个Promise实例中,有一个状态改变,race就跟着改变,其他的不再响应
loadImg('1.jpg'),
loadImg('2.jpg'),
loadImg('3.jpg')
]).then(showImgs)
}
iterator
{
let arr=[1,2];
let map=arr[Symbol.iterator](); //数组里面有内置的iterator接口,可以使用for-of遍历 其实就是调用了iterator的next方法
console.log(map.next()) // {value: 1, done: false}
console.log(map.next()) // {value: 2, done: false}
console.log(map.next()) // {value: undefined, done: true}
}
{
let obj={
a:[1,2,3],
b:[4,5,6],
[Symbol.iterator](){ //自定义一个iterator方法 在for-of循环的时候调用这个方法的next 中括号内可以填入变量作为属性
let index=0;
let arr=obj.a.concat(obj.b); //拼接两个数组,在next方法中返回新数组的值
let len=arr.length;
return{
next(){ //iterator的next方法
if(index<len){
return {
value:arr[index++],
done:false
}
}else{
return{
value:arr[index++],
done:true
}
}
}
}
}
}
for (let i of obj){
console.log(i) //1 2 3 4 5 6
}
}
Generator
{
let generator=function*(){ //通过 “ * ” 标记的函数 就是Generator函数 异步编程的一种解决方案
console.log('执行之前')
yield 'a';
yield 'b';
return 'c'
}
var k=generator(); //获取到generator函数
console.log(k.next()) //执行之前 {value: "a", done: false} 执行yield前面的代码和第 1 个yield后面的代码
console.log(k.next()) //{value: "b", done: false} 执行第 2 个yield后面的代码
console.log(k.next()) //{value: "c", done: true} 执行return
console.log(k.next()) //{value: undefined, done: true}
}
{
let obj={};
obj[Symbol.iterator]=function*(){ // iterator和Generator的搭配使用
yield 1;
yield 2;
yield 3;
}
for (let i of obj){
console.log(i) //1 2 3
}
}
{
let state=function*(){ //通过genenrator函数实现状态机 只能在abc三种状态中循环
while(1){
yield 'A';
yield 'B';
yield 'C;'
}
};
let status =state(); //获取到状态机
console.log(status.next()) // { value:"A",done:false }
console.log(status.next()) // { value:"B",done:false }
console.log(status.next()) // { value:"C",done:false }
console.log(status.next()) // { value:"A",done:false }
console.log(status.next()) // { value:"B",done:false }
console.log(status.next()) // { value:"C",done:false }
}
{
let state=async function(){ //generator函数的语法糖,用法和generator函数相同
while(1){
await 'A';
await 'B';
await 'C;'
}
};
let status =state(); //获取到状态机
console.log(status.next()) // { value:"A",done:false }
console.log(status.next()) // { value:"B",done:false }
console.log(status.next()) // { value:"C",done:false }
console.log(status.next()) // { value:"A",done:false }
console.log(status.next()) // { value:"B",done:false }
console.log(status.next()) // { value:"C",done:false }
}
{
let draw = function(count) { // 抽奖系统
//抽奖逻辑
console.log(`剩余${count}次`)
}
let residue = function*(count) {
console.log(count)
while(count > 0) {
count--;
yield draw(count);
}
}
let start = residue(5);
let btn = document.createElement('button');
btn.id = 'start';
btn.innerHTML = "抽奖";
document.body.appendChild(btn);
document.getElementById('start').addEventListener('click', function() {
start.next()
}, false)
}
{
let ajax =function*(){
yield new Promise(function(resolve,reject){ //长轮询 Generator函数和Promise搭配使用
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.log(d)
}
})
}
pull()
}
Decorator // decorator修饰器的第三方库 core-decorators
{
let readonly=function(target,name,descriptor){ //decorator修饰器 是一个函数 修改类的行为 target:修改的类本身 name:修改的属性的名称
descriptor.writable=false; descriptor:该属性的描述对象
return descriptor
}
// @readonly //也可以放在类的前面
class Test{
@readonly
time(){
return '2018-10-15'
}
}
let test= new Test();
console.log(test.time()) // 2018-10-15
test . time =function(){ // 设置为只读之后,重新赋值会报错
console.log('reset')
}
}
Module模块化
{ // a.js
export let A =123; // export 导出
export function test(){
console.log('test')
}
export class Hello{
hello(){
console.log('hello)
}
}
export default{ //第二种导出方式
A,
test,
Hello
}
}
{ // b.js
import {A,test,Hello} from ' a.js ' //导入 b.js中就拿到了a.js中的元素
import * as lesson from 'a.js' //导入所有,放入lesson合集 通过 lesson.A 这样的方式调用
import lesson from 'a.js' //第二种导入方式 通过像lesson.A这种方式调用
}