ES6_Symbol(八)

Symbol

ES6 新增数据类型

火影忍者例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var 忍者能力级别 = {
神级:'天生外挂、尾兽查克拉、轮回眼、血轮眼、N种血继限界、战斗智商、家族秘术、柱间细胞',
影级:'N种血继限界、血轮眼、轮回眼',
特别上忍:'一种血继限界or种族秘术、血轮眼、尾兽查克拉',
普通忍者:'资质普通、普通家族、无种族秘术'
}

function 创造忍者(category){
if(category in 忍者能力级别){
var desc = 忍者能力级别[category]
console.log(`你的忍者能力是:${category}!\n你具有如下能力:${desc}`);
}else{
console.log('你可能是个普通人、忍者鄙视链底端的存在,最好别出村子!')
}
}

创造忍者('神级') // 通过 Key 你知道你的能力

创造忍者('xxx') // 不存在的 Key 你具有未知的能力
  • 升级:走进科学!每个级别的忍者可能他的基因就不一样,于是创建的时候,你可以知道他的基因序列
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var 忍者能力级别 = {
神级:'32103920139102',
影级:'12312312312312',
特别上忍:'0950905940594',
普通忍者:'00000432423423'
}

function 创造忍者(category){
if(category in 忍者能力级别){
var desc = 忍者能力级别[category]
console.log(`你的基因是:${category}!\n你具有如下基因序列:${desc}`);
}else{
console.log('你可能是个普通人、忍者鄙视链底端的存在,最好别出村子!')
}
}

创造忍者('神级') // 通过 Key 你知道你的能力

创造忍者('xxx') // 不存在的 Key 你具有未知的能力
  • 再次升级:我们知道每个忍者的能力可能天生就不同,于是基因对于我们来说只是用来区分不同
  • Symbol 代表你是独一无二的
1
2
3
4
5
6
7
8
9
10
var 忍者能力级别 = {
神级:Symbol(),
影级:Symbol(),
特别上忍:Symbol(),
普通忍者:Symbol()
}

忍者能力级别['神级'] === 忍者能力级别['神级'] // true
忍者能力级别['神级'] === 忍者能力级别['影级'] // false
忍者能力级别['特别上忍'] === 忍者能力级别['普通忍者'] // false

ES6_Promise(七)

回调函数

1
2
3
4
5
6
7
8
9
10
function myAsync(callback){
setTimeout(function(){
console.log('执行完成');
callback('data');
}, 2000);
}

myAsync(function(data){
console.log(data);
});

Promise 解决了什么痛点

回调地狱 代码如下

1
2
3
4
5
6
7
8
9
10
11
myAsync(function(data){
//第一个请求成功接收到数据 然后根据数据触发第二次请求
console.log('第一个请求完成!')
myAsync2(function(data){
console.log('第二个请求完成!')
myAsync3(function(data){
console.log('第三个请求完成!')
//一直一直的回调 排错是很困难的 代码也恶心
})
})
})

我的第一个Promise使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
let myPromise = new Promise(function(resolve, reject){
//当异步代码执行成功时,我们才会调用resolve(...),
// 当异步代码失败时就会调用reject(...)
//使用setTimeout(...)来模拟异步代码 实际可以是Ajax请求
console.log('异步请求中');
setTimeout(function(){
resolve("成功!"); //2秒后代码执行成功 调用resolve
}, 2000);
});

myPromise.then(function(successMessage){
//successMessage的值是上面调用resolve(...)方法传入的值.
console.log("success! " + successMessage);
});

解决回调地狱之链式操作

Promise的优势在于:

  • 可以在then方法中继续写Promise对象并返回,然后继续调用then来进行回调操作。 是不是有种jquery的感觉!

链式操作的用法

  • Promise只是能够简化层层回调的写法,比传递callback的方式简单
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
function myAsync1(){
var p = new Promise(function(resolve, reject){
//做一些异步操作
setTimeout(function(){
console.log('异步1完成');
resolve('data1');
}, 1000);
});
return p;
}
function myAsync2(){
var p = new Promise(function(resolve, reject){
//做一些异步操作
setTimeout(function(){
console.log('异步2完成');
resolve('data2');
}, 2000);
});
return p;
}
function myAsync3(){
var p = new Promise(function(resolve, reject){
//做一些异步操作
setTimeout(function(){
console.log('异步3完成');
resolve('data3');
}, 2000);
});
return p;
}
//依次的异步操作
myAsync1()
.then(function(data){
console.log(data);
return myAsync2();
})
.then(function(data){
console.log(data);
return myAsync3();
})
.then(function(data){
console.log(data);
});

reject( )是什么鬼?

就是异步操作通常有两种结果一个是成功一个是失败

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
function myAsync(){
var p = new Promise(function(resolve, reject){
//做一些异步操作
setTimeout(function(){
console.log('异步1完成');
var num = Math.random()*100;
if(num>60){
resolve('运气不错通过啦!'+num);
}else{
reject('太差了,分不够!'+num)
}

}, 1000);
});
return p;
}
myAsync()
.then(
function(data){
console.log('resolved');
console.log(data);//成功了 你手气不错!
},
function(reason, data){
console.log('rejected');
console.log(reason);//哎呦 挺倒霉啊! 再来一次吧!!
}
);

catch( ) 你肯定听过 try …catch…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function myAsync(){
var p = new Promise(function(resolve, reject){
//做一些异步操作
setTimeout(function(){
console.log('异步任务完成');
resolve('data');
}, 1000);
});
return p;
}
myAsync()
.then(function(data){
console.log('resolved');
console.log(data);
console.log(xxxx.xxxx); //此处的xxxx.xxxx未定义 报错
})
.catch(function(err){
console.log('rejected');
console.log(err);
});

all( )

Promise的all方法提供了并行执行异步操作的能力,并且在所有异步操作执行完后才执行回调。

1
2
3
4
5
Promise
.all([myAsync1(), myAsync2(), myAsync3()])
.then(function(results){
console.log(results);
});
  • 用Promise.all来执行,all接收一个数组参数,里面的值最终都算返回Promise对象。
  • 这样,三个异步操作是并行执行的,等到它们都执行完后才会进到then里面。
  • 那么,三个异步操作返回的数据哪里去了呢?
  • 都在then里面呢,all会把所有异步操作的结果放进一个数组中传给then,就是上面的results。

race( )

all( ) 的效果实际上是 ==>以”执行时间最慢的”为准执行回调

race( ) 以最快的为准
race的用法与all一样,把上面myAsync3的延时改为0.5秒运行

1
2
3
4
5
6
Promise
.race([myAsync1(), myAsync2(), myAsync3()])
.then(function(results){
//返回三个异步请求最快的那个
console.log(results);
});

ES6_模块化(六)

ES6自带模块化 但是浏览器还不支持

  • 使用webpack 前面已有文章总结了,这里就不说了
  • 还可以使用Google公司的Traceur转码器,也可以将ES6代码转为ES5代码。必须在网页头部加载Traceur库文件。

注意!!注意!! 要运行在服务器环境

服务器是什么?你不会我没法详细和你说

两个工具

  • wamp 搭建服务器 自行百度
  • cnpm install http-server 前提是安装了node 同时设置了淘宝镜像
  • 然后在你当前目录打开命令行 输入 http-server -c-1
    在显示的端口号访问就行了 你还要问细节怎么办?
    那你就回答我 “回”字为什么有四种写法

新建mod.js

1
2
3
4
5
6
let a=12;
let b=5;
export default {
a:a,
b:b
}

index.html文件

1
2
3
4
5
6
7
<script src="https://google.github.io/traceur-compiler/bin/traceur.js"></script>
<script src="https://google.github.io/traceur-compiler/bin/BrowserSystem.js"></script>
<script src="https://google.github.io/traceur-compiler/src/bootstrap.js"></script>
<script type="module">
import mod from './mod.js';
console.log(mod.a) // 打印12
</script>

ES6_面向对象(五)

ES6之前的面向对象使用函数模拟的 并非真正意义上的面向对象

始终坚信一句话 系统提供的API永远是最好的


以前的面向对象
各种恶心复杂版本的实现我就不说了
我猜你肯定要问?(好奇害死猫)
自己看高三第六章

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function Person(name,age){
this.name=name;
this.age=age;
}
Person.prototype.showName=function(){
return this.name;
};
Person.prototype.showAge=function(){
return this.age;
};

//继承
function Worker(name,age,job){
Person.apply(this,arguments);
}
Worker.prototype=new Person();
Worker.prototype.constructor=Worker;

var p1=new Person('aaa',30);
var w1=new Worker('bbb',10,'上学');

//alert(p1.showName());
alert(w1.showName());

真正意义上的面向对象

简易版

1
2
3
4
5
6
7
8
9
10
11
12
class Person{
constructor(name,age){ //构造函数
this.name=name;
this.age=age;
}
showName(){
return this.name;
}
}

var p1=new Person('bbb',40);
alert(p1.showName());

继承

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
class Person{
constructor(name,age){ //构造函数
this.name=name;
this.age=age;
}
showName(){
return this.name;
}
}
//继承
class Worker extends Person{
constructor(name,age,job){
super(name,age);
this.job=job;
}
showJob(){
return this.job;
}
}

var p1=new Person('bbb',40);
var w1=new Worker('aaa',10,'学生');

alert(p1.showJob);
//alert(w1.showJob());

ES6_扩展运算符(四)

扩展运算符 => …

1
2
3
4
5
6
7
8
9
10
// var arr=[1,2,3,4,5];
// var arr2=arr;
// arr2.pop();

// alert(arr);

function show(...arr){
console.log(arr)
}
show([1,2,3,4]) // Array(1)
1
2
3
4
function show(...a){ 
console.log(a.length); //4
}
show(1,2,3,4)

快速复制一个数组

ES6以前

1
2
3
4
5
6
var arr=[1,2,3,4,5];
var arr2=[];

for(var i=0; i<arr.length; i++){
arr2.push(arr[i]);
}

Array.from() 详细使用请点击
Array.from() MDN

1
2
3
var arr=[1,2,3,4,5];

var arr2=Array.from(arr);

用扩展运算符复制数组

1
2
var arr=[1,2,3,4,5];
var arr2=[...arr];

ES6_对象简洁语法与解构赋值(三)

对象简洁语法

赋值

1
2
3
4
5
6
7
8
9
10
11
12
13
var a=12;
var b=5;

/*var json={
a:a,
b:b
};*/
var json={
a, // a:a
b // b:b
};

alert(json.a);

值是函数的形式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var a=12;
/*var json={
a,
show:function(){
alert(1);
}
};*/
var json={
a,
show(){
alert(1);
}
};

json.show()

解构赋值

1
2
3
4
5
6
7
/*
var [a,b,c]=[1,2,3];
alert(a);
*/
var [a,b,[c,d]]=[1,2,[3,4]];

alert(c);
1
2
3
var {a,b}={a:1,b:2};

alert(a);

ES6_箭头函数(二)

基本使用 函数名 = ( )=>’返回值’

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
/*
function show(){
return 1;
}
alert(show());
*/

var show=()=>'welcome';
alert(show());
```

### 带参数的形式

```bash
/*
function show(a){
return a;
}
alert(show(12));
*/

/*
var show=(a,b)=>a+b;
alert(show(12,5));
*/
/*
function rnd(n,m){
return Math.floor(Math.random()*(m-n))+n;
}
alert(rnd(12,90));
*/
//箭头函数的形式
let rnd=(n,m)=>Math.floor(Math.random()*(m-n))+n;

alert(rnd(10,40));

内部有多个语句

1
2
3
4
5
var show=()=>{
alert(1);
alert(2);
}
show();

与之前的差异

干掉了arguments

1
2
3
4
5
6
7
8
9
10
11
12
 /*
function show(){
alert(arguments.length);
}
show(1,2,3);
*/
//干掉了 arguments
var show=()=>{
alert(arguments.length); //ReferenceError: arguments is not defined
}

show(1,2,3);

在DOM事件上使用

1
2
3
4
5
6
7
8
/*
document.onclick=function(){
alert(1);
};
*/
document.onclick=()=>{
alert(1);
};

ES6变量声明(一)

ES6

代码在浏览器环境运行!代码在浏览器环境运行!代码在浏览器环境运行!

我用的google!!!

变量声明 let

最最最基本用法

1
2
let a = 11;
alert(a); // 11

let与var的区别

1
2
3
4
5
//声明后未初始化,输出相同.
var a;
let b;
console.log(a); // undefined
console.log(b); // undefined

使用在声明前的异同

1
2
3
4
5
console.log(a); //输出undefined  ==> 变量提升
var a= 'test var';

console.log(b); //直接报错:ReferenceError: b is not defined
let b = 'test let';

重复声明问题 在相同的函数或块作用域内重新声明同一个变量会引发SyntaxError

1
2
3
4
5
6
7
var a =5;
var a =12;
console.log(a);//必须注释下面的其中一个let声明

let b = 3;
let b = 666; //报错 Identifier 'b' has already been declared
console.log(b)

作用域问题

除了全局作用域和函数作用域,es6新增了块级作用域,即用{ }包裹的代码块。

块级作用域

内层变量和外层变量的值互不影响。内层无法读取外层,外层无法读取内层。

作用域问题

问题1: 如果是let声明的初始化表达式 在for循环外 访问i会报错 如果var声明的就不会报错

1
2
3
4
5
for(let i=0; i<10; i++){

}
//报错
alert(i);

问题2: 如果是let声明的初始化表达式 在for循环外 访问i会报错 如果var声明的就不会报错

1
2
3
4
5
6
7
{
console.log(a); //报错

{let a=12;}

console.log(a) //报错
}

问题3: 事件中的索引问题 ==>简化内部函数代码

工作原理是因为(匿名)内部函数的3个实例引用了变量i的3个不同实例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<body>
<script>
var aBtn=document.querySelectorAll('input');
for(let i=0; i<aBtn.length; i++){
aBtn[i].onclick=function(){
alert(i); //弹出对应的 索引
//如果换成var声明 就会弹出 aBtn.length ==> 3
};
}
</script>
</head>
<body>
<input type="button" value="aaa">
<input type="button" value="bbb">
<input type="button" value="ccc">
</body>

问题4:在程序或者函数的顶层,let并不会像var一样在全局对象上创造一个属性

1
2
3
4
var x = 'global';
let y = 'global';
console.log(this.x); // "global"
console.log(this.y); // undefined

const 常量

特性

  • 声明时就需要赋值,否则报错;一旦声明不可重新赋值,否则报错;
  • 块级作用域
  • 不存在变量提升;
  • 存在暂时性死区;
  • 声明引用类型常量时,const保存的是地址,常量中的属性还是可以变的;

块级作用域

1
2
3
4
5
if(true){
const a=12;
}
//报错 常量的作用域
alert(a);

重复赋值

1
2
3
const a=12;
a=5;
alert(a); // TypeError:Assignment to constant variable.

未初始化就使用

1
2
const a;
alert(a); // Uncaught SyntaxError: Missing initializer in const declaration