一.资料

MDN(Mozilla 开发者网络)
ECMAScript 6 入门(阮一峰)

二.块级作用域绑定

var function 存在变量提升
var 只会提前声明 function 既声明有定义

1
2
3
4
5
console.log(fun1);
function fun1() {
var b = 4;
}
console.log("fun1" in window); //true

let

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// a is not defined
//console.log(a) 报错
//1.没有变量提升
//2.不可以重复声明
//3.不会给window增加属性
let a = 1;
console.log(window.a); //undefined
function getValue() {
if (condition) {
// var value='blue'
let value = "blue";
//其他代码
return value;
} else {
//var 声明变量value 值为undefined
//let const声明变量 value此处不存在
return null;
}
}

const 1.没有变量提升 2.不可以重复声明 3.不会给 window 增加属性
4.const 定义变量,一旦声明必须赋值
5.const 定义是一个常量,不可以重新赋值

1
2
3
4
5
6
7
8
9
const person = {
name: "make",
};
//可以修改对象属性的值
person.name = "greg";
//抛出语法错误
person = {
name: "Greg",
};

块级作用域

{}:一个{}就是一个块级作用域
在块级作用域下,var 和 function 声明变量依然是全局的
在块级作用域下 let 和 const 声明变量都是私有的
{}如果表示一个对象不可以放在行首
{name:'小明'} 看成一个块级作用域

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//用小括号console.log(eval('({name:"小明"})'))
{
let b = 1;
var a = 0;
function getA() {
console.log(a);
}
}
console.log(a); //0
getA(); //0
//console.log(b) //b is not defined
// if(){}中function 只会提前声明不会定义,当条件成立先给函数赋值 代码再执行
if (0) {
var A = 1;
function getAA() {}
}
console.log(A); //undefined
console.log(getAA); //undefined

var 和 let
var和let

临时死区 TDZ
Temporal Dead Zone

1
2
3
4
5
6
7
console.log(typeof value); //引用错误
let value = "123";
// 正确: 当value不存在TDZ
console.log(typeof value); //'undefined'
if (1) {
let value = "blue";
}

三.数组和对象

数组的结构赋值

1
2
3
4
5
6
7
8
let [x, y, m, n] = arr;
console.log(x, y, m, n); //1,2,3,4
//设置默认值 只有后面结构的值是undefined才会走默认值
let [x1, x2 = 10] = [1];
//省略赋值
let [, , m3] = [1, 2, 3]; //m3=3
//不定参数赋值 将后面的项放在一个数组中赋值y3=[3,4,5]
let [y1, y2, ...y3] = [1, 2, 3, 4, 5]; //扩展运算符

对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//如果变量名和属性名一样 可以直接省略写法
let { name, age } = { name: "小明", age: 10 };
console.log(name); //小明
//默认值
let { name, age = 100 } = { name: "小明" };
//嵌套
let {
name,
age,
list: [a1, a2, a3],
} = { name: "小明", age: 10, list: ["js", "node", "vue"] };
console.log(name, age, a1, a2, a3); //小明 10 js node vue
块(
// let x1,x2;
// [x1,x2]=[1,2];
({ x1, x2 } = { x1: 1, x2: 2 })
); //加括号
console.log(x1, x2); //1,2

合并和操作对象
obj

get 和 set

setAndGet

symbol

Symbol 是一个新的基本类型 而且是一个值的类型
symbol

数字和字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
//使用数组的结构赋值的方式,如果等号右边不是一个数组,
// 默认会转化为类数组(类似数组的对象 必须有一个length属性)
let [x, y] = "123";
console.log(x, y); //1,2
//使用对象的结构赋值的形式 如果等号右边不是对象
// 默认转化成对象
let { __proto__: a } = 1;
console.log(a);
console.log(Object(1)); //Number {[[PrimitiveValue]]: 1}
//__proto__:Number
let { length: b } = "1234";
console.log(Object("1,2,3,4")); //String {[[PrimitiveValue]]: "1,2,3,4"}
console.log(b); //4

函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
//函数参数的结构赋值
function getA([a, b, c, ...d]) {
console.log(a, b, c, d); //1,2,3,[4,5]
}
getA([1, 2, 3, 4, 5]);
//默认值
function getB({ name = "小明", age = 10 } = {}) {
console.log(name, age); //小明,10
}
getB();

//设置默认值
function fn(x = "小明", y = "es6") {
console.log(x, y); //0 "es6"
}
fn(0);
//length属性 ,形参的个数,如果形参有默认值情况
// length就会失真
function fn2(x, y = 10) {}
fn2(1, 2);
console.log(fn2.length); //1
//参数默认值位置:一般参数的默认值放在最后面
function fn3(x = 10, y = 20) {}
//fn3(,1)会报错
//arguments 类数组
function fn4(...arg) {
console.log(arguments);
console.log(arg); // [1, 2, 3, 4]
}
fn4(1, 2, 3, 4);
//name的问题
function fn() {}
console.log(fn.name); //"fn"
console.log(function () {}.name); //""
//特殊情况
function fn() {}
//1.bind name是"bound 原来函数的名字"
let fn1 = fn.bind(null);
console.log(fn1.name); //bound fn
//2.通过构造函数创建一个函数 名字叫做"anonymous"
//function fn(形参){函数体}
//new Function("形参","函数体")
//new Function("函数体")
let fn2 = new Function("x,y", "console.log(x,y);return x+y");
console.log(fn2(10, 100)); //110
console.log(fn2.name); //anonymous

bind

1
2
3
4
5
6
7
8
function list() {
return Array.prototype.slice.call(arguments);
}
var list1 = list(1, 2, 3); // [1, 2, 3]
// 预定义参数37
var leadingThirtysevenList = list.bind(undefined, 37);
var list2 = leadingThirtysevenList(); // [37]
var list3 = leadingThirtysevenList(1, 2, 3); // [37, 1, 2, 3]

扩展运算符

将数组变成非数组

1
2
3
4
let arr1 = [1, 2, 3];
let arr2 = [4, 5, 6];
console.log(arr1.concat(arr2)); //[1, 2, 3, 4, 5, 6]
console.log([...arr1, ...arr2]); //[1, 2, 3, 4, 5, 6]

求数组的最大值

1
2
3
4
5
let ary = [1, 22, 35, 66, 77];
//Math.max(1,22,35,66,77)
console.log(Math.max.apply(null, ary)); //77
console.log(eval("Math.max(" + ary + ")")); //77
console.log(Math.max(...ary)); //77

字符串的扩展

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
console.log(String.prototype);
//1.includes 返回值布尔 true/false
//判断字符串中有没有指定字符
//includes("指定字符",开始查找的位置(可选))
//第二个参数是数字,不是会转化成数字Number()
let str = "abcdefg12345";
console.log(str.includes("a", null));
//2.startsWith和endsWith
//startsWith 判断字符串是不是以指定字符作为开头
//stratsWith("指定字符",开始查找的位置(可选))
console.log(str.startsWith("b", 1)); //true
//endsWith 判断字符串是不是以指定字符作为结尾
//endsWith("指定字符",num);
//num:从前num中查看
console.log(str.endsWith("c", 3)); //true
//3.repeat(num) 将字符串重复num次 num取整不可以是负数
// 或者Infinity
console.log(str.repeat(1.9)); //1次abcdefg12345
//0到-1 -0.3取整0
console.log(str.repeat(-0.9)); //空字符
//4.padStart padEnd ES7中的方法
//按照指定字符串补全字符串的指定长度
//参数 1.length长度 2.指定字符
//padStart(length,'指定字符')
let str1 = "ab";
console.log(str1.padStart(7, "ghk")); //ghkghab
console.log(str1.padEnd(7, "ghk")); //abghkgk

操作数组

Array 类上扩展的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
console.dir(Array); //解析字典
//Array 类是一个函数 返回一个数组
//Array(x,y,z)将参数变成一个数组返回[x,y,z]
console.log(Array);
console.log(Array(1, 2, 3)); //[1,2,3]
console.log(Array("1")); //["1"]
//注意:如果只有一个参数并且参数是个数字n,返回有n个空位的数组
console.log(Array(7)); //[empty × 7]
//Array.of(); 跟Array一样的 唯一不同的是 参数是一个数字的时候
//返回仍然是一个只有一项的数组
console.log(Array.of(7)); //[7];
//Array.from(数组/类数组) 返回一个数组
console.log(Array.from([1, 2, 3]));
console.log(Array.from("123")); //["1", "2", "3"]

原型上的扩展方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
console.log(Array.prototype);
//copyWithin 从原数组中读取内容 替换数组的指定的位置的内容
//参数(替换的目标起始位置target,查找的起始的位置begin,查找的结束位置end 默认到末尾)
//原数组的length不变,如果有超出的部分截取掉
let ary1 = [1, 2, 3, 4, 5, 6, 7, 8];
ary1.copyWithin(4, 2, 4);
console.log(ary1); //[1, 2, 3, 4, 3, 4, 7, 8]
ary1.copyWithin(3, 2);
console.log(ary1); //[1, 2, 3, 3, 4, 3, 4, 7]
//fill按照指定字符填充数组
// 将数组的每一项都变成指定字符
console.log(ary1.fill("小明")); //['小明',......]
let ary2 = [1, 2, 3, 4, 5, 6, 7, 8];
ary2.fill("小法", 3, 5); //索引3,4替换
console.log(ary2); //[1, 2, 3, "小法", "小法", 6, 7, 8]
//filter 过滤数组 依据返回值过滤原数组
//返回一个新数组
let ary3 = ["小红", 1, 2, 3, "小黄"];
let arr = ary3.filter(function (item, index) {
//如果返回true就留下当前项
return typeof item == "number";
});
console.log(arr); //[1, 2, 3]
//find 先遍历数组 一旦参数函数返回true 停止查找 返回当前项
//只会找一个
let a = ary3.find(function (item) {
return typeof item == "number";
});
console.log(a); //1
//findIndex先遍历数组 一旦参数函数返回true 停止查找 返回当前项的索引
//只会找一个
let i = ary3.findIndex(function (item) {
return typeof item == "string";
});
console.log(i); //0
//includes 判断数组中有没有某一项
//第二个 参数是查找位置的索引
console.log([1, 2, 3].includes(1, 1)); //false
//every 遍历数组 如果遍历每一项都返回true,最后结果为true
// 有一项false,结果就是false
console.log(
[1, 2, 3, "小明"].every(function (item) {
return typeof item === "number";
})
); //false
//some 遍历数组 如果有一项返回true,最后结果为true
console.log(
[1, 2, 3, "小明"].some(function (item) {
return typeof item === "number";
})
); //true
//reduce 迭代 第二个参数作为初始的prev
let ary4 = [1, 2, 3, 4, 5];
let result = ary4.reduce(function (prev, item) {
//prev 上一次返回值 item:当前项
return prev + item;
}, 0); //求和
console.log(result); //15
/*
* prev item prev+item
* 0 1 0+1=1
* 1 2 1+2=3
* 1+2 3 1+2+3=6
* 1+2+3 4 1+2+3+4=10
* 1+2+3+4 5 1+2+3+4+5=15
* */
//reduceRight 跟reduce一样 只是顺序从右开始
//keys 遍历每一项的索引的接口 使用for of 遍历
let ary5 = [1, 2, 3, 4];
for (let key of ary5.keys()) {
console.log(key); //0,1,2,3 (索引)
}
//默认使用for of 遍历数组 默认遍历的就是每一项
let ary6 = ["a", "b", "c"];
for (let item of ary6) {
console.log(item); //a b c
}
//entries 遍历接口 可以遍历到索引的每一项
//每一项遍历得到一个数组[索引,当前项]
//一般可以通过数组的结构赋值获取遍历的结构
//let [index,item] of ary6.entries()
for (let e of ary6.entries()) {
console.log(e); //[0, "a"] [1,"b"] [2,"c]
}

处理数组数据

数据的变异(以下能改变原数组)
pop push unshift shift splice reverse sort
查找合并
indexof(查找位置) lastIndexof concat slice

处理数据
forEach filter(过滤) map(映射) some every reduce (include find es6)

of

of
of 对象会报错 obj is not iterble(迭代)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
let arr = [1, 2, 3, 4, 5];
for (let i = 0; i < arr.length; i++) {
//编程
console.log(arr[i]);
}
// 1.forEach 不支持return
arr.forEach(function (item) {
//声明式(不关心如何实现)
console.log(item);
});
arr.b = "100";
for (let key in arr) {
//key会变成字符串类型,包括数组的私有属性
console.log(typeof key); //6个string
}
for (let val of arr) {
//支持return 并且是值of数组(不能遍历对象)
console.log(val); //12345
}
// Object.keys()
let obj = { name: "cwx", age: 23 };
for (let val of Object.keys(obj)) {
console.log(obj[val]); //cwx 23
}

filter

删除
filter 是否操作原数组: 不 返回结果 : 过滤后的新数组 回调函数的返回结果:
如果返回 true 表示这一项放在数组中

1
2
3
4
let newArr = [1, 2, 3, 4, 5].filter(function (item, index) {
return item > 2 && item < 5;
});
console.log(newArr); //[3,4]

map

更新
map 映射 将原有的数组映射成一个新的数组[1,2,3]
<li>1</li><li>2</li><li>3</li>
不操作原数组 返回新数组 回调函数中返回什么这一项就是什么

1
2
3
4
let arr1 = [1, 2, 3].map(function (item) {
return `<li>${item}</li>`; //es6 模板字符串 遇到变量用${}取值
});
console.log(arr1.join("")); //<li>1</li><li>2</li><li>3</li>

includes

返回布尔值

1
2
let arr2 = [1, 2, 3, 4, 55];
console.log(arr2.includes(5)); //false

find

返回找到的那一项 不会改变数组 回调函数中返回 true 表示找到了,找到后停止循环

1
2
3
4
5
6
let arr2 = [1, 2, 3, 4, 55, 555];
//找到具体的某一项用find,找不到结果为undefined
let result = arr2.find(function (item, index) {
return item.toString().indexOf(5) > -1;
});
console.log(result); //55

some 和 every

some 找 true 找到 true 后停止 返回 true

1
2
3
4
5
6
let arr2 = [1, 2, 3, 4, 55, 555];
let result = arr2.some(function (item, index) {
return item.toString().indexOf(5) > -1;
});
console.log(result); //true
//every 找false 找到false后停止 返回false

reduce

reduce 收敛四个参数 返回的是叠加后的结果 原数组不发生变化,回调函数返回的结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
let arr3 = [1, 2, 3, 4, 5];
let sum = arr3.reduce(function (prev, next, index, item) {
console.log(arguments);
// { '0': 1, '1': 2, '2': 1, '3': [ 1, 2, 3, 4, 5 ] }
// { '0': 3, '1': 3, '2': 2, '3': [ 1, 2, 3, 4, 5 ] }
// { '0': 6, '1': 4, '2': 3, '3': [ 1, 2, 3, 4, 5 ] }
// { '0': 10, '1': 5, '2': 4, '3': [ 1, 2, 3, 4, 5 ] }
return prev + next; //求和
});
console.log(sum); //15
//对象里数求和
let obj1 = [
{ price: 30, count: 2 },
{ price: 20, count: 3 },
];
let sum2 = obj1.reduce(function (prev, next) {
return prev + next.price * next.count;
}, 0); //默认指定第一次的prev
console.log(sum2); //120

数组扁平结合

1
2
3
4
5
6
7
let flat = [
[1, 2, 3],
[4, 5, 6],
].reduce(function (prev, next) {
return prev.concat(next);
});
console.log(flat); //[1,2,3,4,5,6]

defineProperty

1
2
3
4
5
6
7
let obj = {};
Object.defineProperty(obj, "name", {
configurable: false, //操作是否删除 delete obj.name
writable: false, //是否可重新赋值
enumerable: false, //是否可枚举(key in obj)
value: 1,
});

双向

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<input type="text" id="input" />
<script>
let input = document.getElementById("input");
let obj = {};
let temp = {};
Object.defineProperty(obj, "name", {
get() {
// 取obj中的name属性触发
return temp["name"];
},
set(val) {
//给obj赋值会触发get方法
temp["name"] = val; //改变temp的结果
input.value = val; //将值赋值给输入框
},
});
input.value = obj.name; //页面一加载就会调用get方法
input.addEventListener("input", function () {
obj.name = this.value; //当值发生变化时,调用set方法
});
</script>

四.箭头函数

fn

arrow fn 不具备有 this,arguments
自己家没有 this 就找上一级的 this
如何更改 this 指向

  • 1.call apply bind
  • 2.var that=this
  • 3.=>

如何确定 this 是谁 看谁调用的 .前面是谁 this 就是谁

1
2
3
4
5
6
7
8
9
10
11
function a(b) {
return b + 1;
}
let a = (b) => b + 1; //去掉function关键字 参数只有一个可以省略小括号 小括号和大括号之间有一个箭头
// 如果没有大括号则直接是返回值
// 有括号必须写return
let a = (b) => (c) => b + c; //高阶函数 (>=2个箭头)
console
.log(a(1)(2)) //3
[(1, 2, 3)].forEach((item) => console.log(item)); //错误
//在Vue中很多时候不能用箭头函数

五.promise

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
//执行顺顺序
//new promise() 中的函数==>当前队列中的同步代码==>then中的回调
let pro1 = new Promise((resolve, reject) => {
//resolve 函数
//reject 函数
//只能执行一个
resolve("success"); //成功
reject("error"); //失败
});
pro1.then(
(res) => {
//成功的回调
console.log(res);
},
(e) => {
//失败
console.log(e);
}
);
//catch promise捕获错误的,then中也会捕获错误
pro1.then((res) => {}).catch((e) => {});
//resolve 代表是转向成功(函数)
//reject 失败(函数)
//promise的实例就一个then方法,then方法中有两个参数
let p = new Promise((resolve, reject) => {
setTimeout(() => {
let a = "蘑菇";
resolve(a);
//reject()
}, 2000);
});
p.then(
(data) => {
console.log(data);
},
(err) => {
console.log("err");
}
); //蘑菇

promise

ajax

ajax

All

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//console.dir(Promise);
//Promise.all([每一项都是Promise,如果不是默认会转化为Promise])
//数组中每一项都是成功状态 才会总成功回调 默认将每一项的参数放在一个数组中传给回调函数
let p1 = new Promise((resolve, reject) => {
resolve("ok");
});
let p2 = new Promise((resolve, reject) => {
resolve("vue");
});
let pAll = Promise.all([p1, p2]);
console.log(pAll); //Promise { <pending> }
pAll
.then((res) => {
console.log(res); //[ 'ok', 'vue' ]
})
.catch((e) => {
//有个错就执行
console.log(e);
});

race

1
2
3
4
5
6
7
8
9
10
//Promise.race([p1,p2])
//只要有一个状态改变,当前实例的状态就跟着改变
//执行一个
Promise.race([p1, p2])
.then((res) => {
console.log(res);
})
.catch((err) => {
console.log(err);
});

六.set 和 map

Set

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
//类似数组 只有值value 没有键key
//通过构造函数方式创建一个set实例
//参数是一个数组(或者是类似数组只有是有iterable接口)
//有iterable接口:数组,arguments,元素集合,Set,Map,字符串
//默认有去重
console.log(new Set([1, 2, 3, 4])); //Set(4) {1, 2, 3, 4}
console.log(new Set("1234")); //Set(4) {"1", "2", "3", "4"}
function fn() {
console.log(new Set(arguments));
}
fn(1, 2, 3, 4, 2, 2); //Set(4) {1, 2, 3, 4}
//size 实例的大小个数
//add clear delete has
//add 增加 如果之前没有加上,有就不加上,返回值增加后的Set实例
//可以实现链式写法 参数一次加一个
let set1 = new Set([1, 2, "呵呵", null, NaN]);
console.log(set1.add(10).add(100)); //{1, 2, "呵呵", null, NaN,10,100}
//delete (删除的值) 返回值 true/false 如果里面有这一项就删除成功true
//没有此项删除失败false
console.log(set1.delete(1)); //true;
//clear 清空 没有返回值 undefined,没有参数
console.log(set1.clear()); //undefined
console.log(set1); //Set(0) {}
//has判断由没有此项,返回值true/false
let set2 = new Set([1, 2, "哈哈", NaN]);
console.log(set2.has(NaN)); //true
//遍历forEach keys values entries
set2.forEach((item, index, input) => {
//Set实例只有value没有key
//item,index:当前value
//input:当前Set实例
});
for (let key of set2.keys()) {
//key 仍然是value值
console.log(key); //1 2 哈哈 NaN
}
for (let val of set2.values()) {
//val 是value值
console.log(val); //1 2 哈哈 NaN
}
for (let [item, val] of set2.entries()) {
//item,val 是value值
console.log(item, val); //1 1 2 2 哈哈 哈哈 NaN NaN
}

数组去重

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//数组去重
let ary = [1, 1, 2, 2, 3, 4, 4];
console.log([...new Set(ary)]); //[1, 2, 3, 4]
function unique() {
return [...new set(ary)];
//return Array.from(new Set(ary))
}
let ary1 = [1, 3, 5, 7, 8, 9];
let ary2 = [2, 4, 6, 7, 8, 9];
//并集
function add(ary1, ary2) {
return [...new Set([...ary1, ...ary2])];
}
console.log(add(ary1, ary2)); // [1, 3, 5, 7, 8, 9, 2, 4, 6]
//交集
function same(ary1, ary2) {
return ary1.filter((item) => ary2.includes(item));
}
console.log(same(ary1, ary2)); //[7, 8, 9]
//差集=并集-交集
function diff(ary1, ary2) {
return add(ary1, ary2).filter((item) => !same(ary1, ary2).includes(item));
}
console.log(diff(ary1, ary2)); //[1, 3, 5, 2, 4, 6]

Map

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
//Map
//构造函数方式创建一个Map实例
//new Map([[key,value],[]])
//参数是一个数组,数组每一项也是一个数组,有两项key,value
//一个对象, 属性名必须是字符串,如果写的不是字符串也默认转化为字符串
//Map实例的key可以是任意的数据类型
let obj = {
name: "小明",
1: "1",
true: "true",
};
new Map([
[{ name: "小明" }, "小明"],
[2, "小红"],
]);
let map1 = new Map([
[1, "小明"],
[2, "小红"],
]);
console.log(map1);
//0:{1 => "小明"}1:{2 => "小红"}
//size 键值对的个数
//get set has delete value entries
//get 获取value
console.log(map1.get(1)); //小明
//set(key,value) 可以实现链式写法
//has has(1)判断key有没有对应的value
//delete delete(1)删除属性key 返回值true/false
//clear clear()清空
//遍历 forEach keys values entries
map1.forEach((value, key, input) => {});
for (let key of map1.keys()) {
}
//数组变成Map实例
let ary = ["vue", "node", "React"];
let map3 = new Map();
for (let [index, item] of ary.entries()) {
map3.set(index, item);
}
console.log(map3);

七.Proxy

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
//代理
//对目标对象默认操作的拦截/改写
//new Proxy({目标对象target},{拦截的方法})
let obj = { name: "小明", age: "18" };
//让proxy1代理obj 需要通过proxy1 去操作代理的obj
let proxy1 = new Proxy(obj, {
get(target, key, proxy) {
//target:原对象
//key;属性名
//peoxy:实例
console.log("get拦截");
//这里return声什么 获取就是什么
return target[key];
},
});
//get 只要是获取,例如:proxy1.name就会触发get
console.log(proxy1.name); //小明
//set(target,propKey,value,receiver(接收器))
let obj = { name: "小法" };
let proxy = new Proxy(obj, {
get(target, propKey, receiver) {
return target[propKey];
},
set(target, propKey, value, receiver) {
console.log("设置");
//propKey:设置的属性名
//value:设置的属性名
target[propKey] = value;
return true;
},
has(target, propKey) {
console.log("has");
if (propKey.startsWith("_")) {
//拦截下划线开头
return false;
}
return propKey in target;
},
});
proxy.age = "18";
console.log(proxy); //Proxy {name: "小法", age: "18"}
console.log("name" in proxy); //true
console.log("__proto__" in proxy); //false

apply

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function getObj() {
console.log(this);
return { name: "小米" };
}
let proxy1 = new Proxy(getObj, {
apply(target, object, args) {
//函数直接执行(),call执行,apply执行
//console.log("apply");
console.log(target, object, args);
//target getObj函数
//args 函数执行的参数
//object 给函数修改this的
if (object) {
object.__proto__.fn = target;
object.fn(...args);
delete object.__proto__.fn;
} else {
target(...args);
}
},
});
proxy1(1, 2); //this-->window
proxy1.call(obj, 1, 2); //this-->obj

八.class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//constructor 相当于函数本身
function Fn() {
this.x = 10;
}
Fn.prototype.getX = function () {};
let f = new Fn();
//Fn()
//es6
class A {
constructor() {
//当前类本身的函数,
//this :当前实例
this.x = 10; //增加私有属性
//return 的是基本数据类型对实例没有影响
//如果是引用数据类型会改变实例的结果(一般不写return)
}
}
let a = new A(10); //A x:10
console.log(a);
//A();类必须使用new执行
console.log(typeof A); // function

class 的 name 的问题

1
2
3
4
5
6
7
8
9
10
11
12
let A = class AA {
//AA只在类里面使用
constructor() {
console.log(AA.name); //AA
}
getA() {
console.log(AA.name); //AA
}
};
let a = new A();
console.log(A.name); //AA
a.getA(); //AA

执行的问题

1
2
3
4
5
6
//采用class表达式让类直接执行
let a1 = new (class {
constructor(name) {
console.log(name);
}
})("杨小虎"); //杨小虎

class 是没有变量提升的

1
2
3
4
5
6
7
//Es6 中的class 和let,const一样没有变量提升
new GG(); //GG is not defined
class GG {
constructor() {
this.gg = "gg";
}
}

class 的静态方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
//类就相当于原型,写在原型上的方法都被实例继承了
//假如想给当前类本身加一些方法,可以在方法前面加上一个
// 关键字static 不会被实例继承,只有类本身可以使用
//例如 Array.of
class AA{
constructor(){
this.a='aa';
}
getA(){
console.log("哈哈");
}
static getB(){
console.log("我是AA的静态方法");
}
}
let aa=new AA();
console.log(aa);//AA { a: 'aa' }
aa.getA()//哈哈
console.log(aa.getB);//undefined
AA.getB()//我是AA的静态方法
//静态方法可以被子类继承
class F{
static getF(){
console.log("我是F的getF")
}
};
class G extends F{
static getG(){
super.getF()
}
}
G.getG()//我是F的getF
//es6原型上的方法不可以枚举
1.function F(){
this.f='ff';
}
F.prototype.getF=function () {
let f=new F;
for(let key in f){
console.log(key)
}
};
let f=new F();
f.getF()//f getF 可以枚举
2.class FF{
constructor(){
this.ff="ff"
}
getF(){};
}
let ff=new FF();
for (let key in ff){
console.log(key)//ff 不可枚举
}
console.log(Object.getOwnPropertyDescriptor(FF.prototype, "getF"));
/* { value: [Function: getF],
writable: true,
enumerable: false,不可枚举
configurable: true }*/

继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
class A {
constructor(x) {
this.x = x;
}
getX() {
console.log(this.x);
}
static getY() {
console.log(this);
}
}
A.getY(); //[Function: A]
//子类B继承父类A
class B extends A {
constructor(x) {
//子类没有this this继承父类
//super()执行完成之后才有this
//super() 就是父类A的constructor
//this.y=100;不可以在super执行之前使用this
super(x);
this.y = 100;
}
getX() {
//super 指向父类A的原型
super.getX();
}
//static 父类的静态/私有方法也可以继承
getY() {
//super 指向父类本身
super.getY();
}
}
let b = new B("熊猫");
b.getX(); //熊猫
B.getY(); //[Function: B]

九.async

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//async 函数默认返回一个promise对象
async function getA() {
//return 出的内容就是成功的回调的参数
//这里有错误就会被catch捕获到
throw new Error("对不起");
return "小明";
}
getA()
.then((res) => {
console.log(res);
})
.catch((e) => {
console.log(e);
});

await

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
let p = new Promise((resolve, reject) => {
resolve("小明");
});
async function getA() {
//await 后面是一个promise的实例,如果不是也会转化Promise
//直接让promise实例的回调执行,返回执行时的参数
//await 是一个语法糖 不用通过then就可以拿到resolve或者reject的参数
let a = await p;
//等await 后面的异步完成中再去执行后面的代码
//console.log(a)//小明
return a;
}
getA()
.then((res) => {
console.log(res);
})
.catch((e) => {
console.log(e);
});

十.迭代器和生成器

迭代器,是 ES6 引入的一种新的遍历机制,主要讲解的是 Iterator 、迭代过程、可迭代的数据结构

Iterator 是 ES6 引入的一种新的遍历机制,迭代器有两个核心概念:

  1. 迭代器是一个统一的接口,它的作用是使各种数据结构可被便捷的访问,它是通过一个键为 Symbol.iterator 的方法来实现;

  2. 迭代器是用于遍历数据结构元素的指针(如数据库中的游标)。

1
2
3
4
5
6
7
8
9
10
const items = ["zero", "one", "two"];
const it = items[Symbol.iterator]();
it.next();
//{value: "zero", done: false}
it.next();
//{value: "one", done: false}
it.next();
//{value: "two", done: false}
it.next();
//{value: undefined, done: true} 当done为true时则遍历结束

String,Array,Map,Set,Dom 元素是所有内置的可迭代对象,他们的原型对象都有一个 [Symbol.iterator] 方法。

我们将使用 for…of 循环(参见下文的 for…of 循环)对数据结构进行迭代。

1
2
3
4
5
6
7
//JavaScript
for (let item of ["zero", "one", "two"]) {
console.log(item);
}
// zero
// one
// two

迭代器用法二

1
2
3
4
5
6
7
const str = "wecy";
const iterator = str[Symbol.iterator](); // 返回一个{next:方法}对象
let obj = null;
do {
obj = iterator.next(); // 返回的是对象,{value:任意对象,done:布尔型}
console.log(obj.value); //w e c y undefined (依次打印)
} while (!obj.done);

生成器案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// 获取用户数据, 订单数据, 商品数据
function getUser() {
setTimeout(() => {
let data = '用户数据'
iterator.next(data)
}, 1000)
}

function getOrder() {
setTimeout(() => {
let data = '订单数据'
iterator.next(data)
}, 1000)
}

function getGoods() {
setTimeout(() => {
let data = '商品数据'
iterator.next(data)
}, 1000)
}

function* gen() {
let user = yield getUser()
console.log(user); //用户数据
let order = yield getOrder()
console.log(order); //订单数据
let goods = yield getGoods()
console.log(goods); //商品数据
}
// 调用生成器函数
let iterator = gen()
iterator.next()