本文的学习来自技术胖大神的教程:https://jspang.com/

1扩展运算符和rest运算符

扩展运算符和rest运算符,它们都是…(三个点)。

它们有很多相似之处,甚至很多时候不用特意去区分。

它们可以很好的解决参数和对象数组未知情况下的编程,让代码更健壮和简洁。

1.1对象扩展运算符(…)

当编写一个方法时,允许它传入的参数是不确定的。这时候可以使用对象扩展运算符来作参数。

例:

function test(...arg){
console.log(arg[0]);
console.log(arg[1]);
console.log(arg[2]);
console.log(arg[3]);
}
test(1,2,3);

说明可以传入多个值,并且就算方法中引用多了也不会报错。

1.2扩展运算符的用处

例1:声明两个数组arr1和arr2,然后把arr1赋值给arr2,然后改变arr2的值:

let arr1=['a','b','c'];
let arr2=arr1;
console.log(arr2);
arr2.push('d');
console.log(arr1);

可以看到arr1的值也改变了,因为这是对内存堆栈的引用,而不是真正的赋值。

利用对象扩展运算符简单的解决这个问题:

let arr1=['a','b','c'];
let arr2=[...arr1];
console.log("arr2:",arr2);
arr2.push('d');
console.log("arr1:",arr1);
console.log("arr2:",arr2);

可以看到arr1并没有改变。

1.3 rest运算符

例:

function test(first,...arg){
console.log(arg.length);
}
test(1,2,3,4,5,6);

第一个参数1传给了first,剩下的参数传给了arg数组,所以arg长度为5

1.4循环输出rest运算符

可以用for…of循环,for…of的循环可以避免开拓内存空间,增加代码运行效率:

function test(first,...arg){
for(let val of arg){
console.log(val);
}
}
test(1,2,3,4,5,6);

2 ES6新增的数字操作

2.1二进制声明(不是ES6特性)

二进制的英文单词是Binary,二进制的开始是0(零),然后第二个位置是b(大小写都可以实现),然后跟上二进制的值就可以了。

2.2八进制声明(不是ES6特性)

八进制的英文单词是Octal,也是以0(零)开始的,然后第二个位置是O,然后跟上八进制的值就可以了。

例:

//二进制声明
let binary=0B010101;
console.log('二进制binary:',binary); //八进制声明
let octal=0O777;
console.log('八进制octal:',octal);

2.3数字验证

可以用Number.isFinite( )进行数字验证,只要是数字,不论是浮点型还是整形都会返回true,其他时候会返回false

console.log(Number.isFinite(888));
console.log(Number.isFinite(11/4));
console.log(Number.isFinite('abc'));
console.log(Number.isFinite(NaN));
console.log(Number.isFinite(undefined));

2.4 NaN验证

NaN是特殊的非数字,可以使用Number.isNaN()来进行验证

console.log(Number.isNaN(0));
console.log(Number.isNaN(NaN));

2.5判断是否为整数

Number.isInteger()
console.log(Number.isInteger(100));
console.log(Number.isInteger(99.99));

2.6转换

整数转换Number.parseInt()

浮点型转换Number.parseFloat()

let a='9.99';
let b='aaa';
console.log(Number.parseInt(a));
console.log(Number.parseFloat(a));
console.log(Number.parseInt(b));
console.log(Number.parseFloat(b));

2.7整数取值范围

整数的操作是有一个取值范围的,就是-(253-1)到253-1。

在计算时会经常超出这个值,所以要进行判断,ES6提供了两个常数,就不用去计算了,直接用就可以:

//最大安全整数
console.log(Number.MAX_SAFE_INTEGER);
//最小安全整数
console.log(Number.MIN_SAFE_INTEGER);

安全整数判断:

let c=Math.pow(2,53);
let d=Math.pow(2,53)-1;
console.log(Number.isSafeInteger(c));
console.log(Number.isSafeInteger(d));

3新增的数组知识

3.1 JSON数组格式转换:Array.from()方法

JSON的数组格式就是为了前端快速的把JSON转换成数组的一种格式

例:

let json={
0:1,
1:2,
2:'abc',
length:3
}

这就是一个标准的JSON数组格式(注意key值就是0,1,2...,不能随意起别的键名),跟普通的JSON对比是在最后多了一个length属性,没有length就只是字符串,有length才是数组。

这种特殊的json格式可以使用ES6的语法转变成数组:

let json={
0:1,
1:2,
2:'abc',
length:3
}
let arr=Array.from(json);
console.log(arr);

3.2 Array.of()方法

可以把一堆文本或者变量转换成数组。(之前可以用eval来进行转换,但是eval的效率很低,会拖慢程序,所以尽量不要用)

例:

let arr=Array.of(1,2,3,4);
console.log(arr); let arr2=Array.of('a','b','c');
console.log(arr2);

3.3 find()方法

find()是一个实例方法,实例方法就是必须有一个已经存在的数组来调用,而前面两个方法是用Array对象直接调用的。

(java中曾学过静态方法和实例方法,所以这里很好理解)

find方法是从数组中查找,需要传入一个匿名函数,函数需要传入三个参数:

value:表示当前查找的值。

index:表示当前查找的数组索引。

arr:表示当前数组。

在函数中如果找到符合条件的数组元素就进行return,并停止查找。如果没有满足条件的,就返回undefinded。

例1:

let arr=[1,2,3,4,5];
console.log(arr.find(function(val,index,arr){
return val>3;
}));

例2:

let arr1=['a','b','c'];
console.log(arr1.find(function(val,index,arr){
return val=='d';
}));

3.4 fill()方法

fill()也是一个实例方法,它的作用是把数组进行填充,它接收三个参数,第一个参数是填充的变量,第二个是开始填充的位置,第三个是填充到的位置。

例:

let arr=[1,2,3,4,5];
arr.fill('abc',2,4);
console.log(arr);

3.5数组的遍历

1) for…of循环

这种形式比ES5的for循环要简单而且高效,比普通for少声明一个i,这个i用完就没意义了。

(for of就类似java中的增强for)

例:

let arr=[1,2,3,4,5];
for(let item of arr){
console.log(item);
}

输出数组索引:

let arr=[1,2,3,4,5];
for(let index of arr.keys()){
console.log(index);
}

同时输出数组的内容和索引:

let arr2=['你好','abc','12345'];
for(let [index,item] of arr2.entries()){
console.log(index+':'+item);
}

2)forEach

forEach循环会自动省略为空的数组元素,相当于直接筛空了。

let arr=['abc','123','Hello'];
arr.forEach((val,index)=>console.log(index,val));

(这里用了箭头函数,先用一下,后面会再详细写)

3)filter

let arr=['abc','123','Hello'];
arr.filter(x=>console.log(x));

4)some

let arr=['abc','123','Hello'];
arr.some(x=>console.log(x));

5)map

map起到一个替换的作用:

let arr=['abc','123','Hello'];
console.log(arr.map(x=>'替换后的值'));

3.6数组转换字符串

1)join()方法

join()方法就是在数组元素中间,加了一些间隔,开发中很有用处。

let arr=['abc','123','Hello','你好'];
console.log(arr.join('-'));

2)toString()方法

转换时只是用逗号隔开了:

let arr=['abc','123','Hello','你好'];
console.log(arr.toString());

3.7 entries()方法

entries()生成的是Iterator形式的数组,这种形式的好处是可以在需要时用next()手动跳转到下一个值。Entries的意思是条目。

例:

let arr=['abc','你好','学习es6'];
let list=arr.entries();
console.log(list);
console.log(list.next().value);

当想生成一些不规则的循环时,就可以用entries,这就叫手动循环。(上面的for of循环叫自动循环)

例:

let arr=['abc','你好','学习es6'];
let list=arr.entries();
console.log(list.next().value);
console.log('---------------');
console.log(list.next().value);
console.log('***************');
console.log(list.next().value);
console.log('@@@@@@@@@@@@@@@');
console.log(list.next().value);

3.8 in的用法

in是用来判断对象或者数组中是否存在某个值的。

例:对象判断

let obj={
a:'你好',
b:'你是谁'
}
console.log('a' in obj);
console.log('你好' in obj);

说明判断的是key值

例:数组判断:

以前会使用length属性进行判断,其存在弊端:

let arr=[,,,];
console.log(arr.length);

数组中其实全是空值,却输出了长度为3,这是不准确的。

用ES6的in就可以解决这个问题:

let arr=[,,,];
console.log(0 in arr); let arr2=[1,2,3,];
console.log(0 in arr2);

注意:这里的0指的是数组下标位置是否为空。

4新增的函数知识

4.1参数的默认值

function fun1(a,b=1){
return a+b;
}
console.log(fun1(2));

4.2主动抛出错误

function fun2(a){
if(a==1){
throw new Error("这里报错了!");
}
return a+b;
}
console.log(fun2(1));

4.3严谨模式

之前严谨模式必须写在代码最上边,相当于全局使用,在ES6中可以写在函数体中,相当于针对函数来使用。

例:

function fun3(a,b=2){
'use strict'
return a+b;
}
console.log(fun3(1));

说明使用了默认值,再使用严谨模式的话,就会有冲突。

把默认值去掉:

function fun3(a,b){
'use strict'
return a+b;
}
console.log(fun3(1,2));

4.4获得需要传递的参数个数

function fun4(a,b){
return a+b;
}
console.log(fun4.length);

如果加上默认值:

function fun4(a,b=1){
return a+b;
}
console.log(fun4.length);

这说明length表示必须传入的参数个数。

4.5对象的函数解构

实际作用:后端经常返回来JSON格式的数据,直接把这个JSON格式数据当作参数,传递到函数内部进行处理。

例:

let json={
a:'abc',
b:'123'
}
function fun({a,b}){
console.log(a,b);
}
fun(json);

这样方便了很多,不用一个个传递参数了。

4.6数组的函数解构

let arr=['abc','123','哈哈'];
function test(a,b,c){
console.log(a,b,c);
}
test(...arr);

4.7最后的参数可以带逗号

之前是不能有,有了报错,现在没关系了

function show(a,b,c,){
console.log(a,b,c);
}
show(1,2,3,);

这个在实际开发中会带来方便。

4.8箭头函数

箭头函数使用频率非常高,所以单独总结了:

https://www.cnblogs.com/hzhjxx/p/12046043.html

5 ES6中对象

5.1对象赋值

原来怎么赋值的:

let name='小笼包';
let age=18; let obj={
name:name,
age:age
}
console.log(obj);

ES6允许把声明的变量直接赋值给对象。不用写key值了,直接把变量放进去,这样就大大简化了:

let name='小笼包';
let age=18; let obj={name,age}
console.log(obj);

5.2对象Key值构建

有时候前台不知道key值的名称,是要从后台取的,这时可以用[ ] 的形式,进行对象的构建:

let key='name';
let obj={
[key]:'前台定义的值'
}
console.log(obj);

5.3 is()方法

把两个对象进行比较。

之前可以用===来比较:

let obj1={name:'名字'};
let obj2={name:'名字'};
console.log(obj1.name===obj2.name);

现在可以用is方法:

let obj1={name:'名字'};
let obj2={name:'名字'};
console.log(Object.is(obj1.name,obj2.name));

这两种比较的区别:

===为同值相等,is()为严格相等

console.log(+0===-0);
console.log(Object.is(+0,-0));

console.log(NaN===NaN);
console.log(Object.is(NaN,NaN));

5.4 assign()合并对象

let a={
name:'名字'
}
let b={
age:20
}
let c={
like:'web'
}
let d=Object.assign(a,b,c);
console.log(d);

如果有重复的key值,后面的会覆盖前面的:

let a={
name:'名字'
}
let b={
age:20,
name:'名字2'
}
let c={
like:'web',
age:22,
}
let d=Object.assign(a,b,c);
console.log(d);

6 Symbol在对象中的应用

6.1用Symbol构建对象的Key

let sy=Symbol();
let obj={
[sy]:'sy的值'
}
console.log(obj[sy]);
obj[sy]='新值';
console.log(obj[sy]);

6.2 Symbol对象元素的保护作用

在对象中有很多值,但是循环输出时,并不希望全部输出,就可以使用Symbol进行保护

let obj={
name:'名字',
like:'吃'
}
let age=Symbol();
obj[age]=18;
console.log(obj);
for(let item in obj){
console.log(obj[item]);
}

可以看到,age被保护了。

7 Set和WeakSet数据结构

Set的定义和一些常用方法可以看这里:https://www.cnblogs.com/hzhjxx/p/11460420.html

7.1set的遍历

1)用for...of

let setArr=new Set(['abc','Hello','123']);
for(let item of setArr){
console.log(item);
}

2)forEach:

let setArr=new Set(['abc','Hello','123']);
setArr.forEach((val)=>console.log(val));

7.2 WeakSet

注意不能直接在new 的时候放入值,会报错,要先把对象定义好,再用add方法添进去。

let weakObj=new WeakSet();
let obj={
name:'大美女',
age:'18'
}
weakObj.add(obj);
console.log(weakObj);

WeakSet里边的值不允许有重复的对象:

let weakObj=new WeakSet();
let obj={
name:'大美女',
age:'18'
}
let obj2={
name:'大美女',
age:'18'
}
weakObj.add(obj);
weakObj.add(obj2);
console.log(weakObj);

因为obj和obj2不是同一个对象。

如果是同一个:

let weakObj=new WeakSet();
let obj={
name:'大美女',
age:'18'
}
let obj2=obj;
weakObj.add(obj);
weakObj.add(obj2);
console.log(weakObj);

8 Map数据结构

先看一个json对象的取值:

let json={
name:'大美女',
age:18
}
console.log(json.name);

这种方法其实是需要遍历整个对象进行寻找的,所以效率要比数组低。

8.1声明Map

let map=new Map();

用set方法添加值:

let json={
name:'大美女',
age:18
}
let map=new Map();
map.set(json,'me');
console.log(map);

map的灵活性就在此,key值和value值可以没规律,可以是任意类型。

8.2方法和属性

let json={
name:'大美女',
age:18
}
let map=new Map(); //添加值
map.set(json,'me');
map.set('me2',json); //长度
console.log(map.size); //取值
console.log(map.get(json));
console.log(map.get('me2')); //查找
console.log(map.has(json)); //删除
map.delete(json);
console.log(map); //清空
map.clear();
console.log(map);

Map应用广泛,因为他更灵活,更高效。

9用Proxy进行预处理

当操作一个对象或者方法时会有几种动作,例如在运行函数前初始化一些数据,在改变对象值后做一些善后处理。这些都算钩子函数。

Proxy的存在就可以给函数加上这样的钩子函数,可以理解为在执行方法前预处理一些代码。也可以简单的理解为是函数或者对象的生命周期。

Proxy的应用可以使函数更加强大,业务逻辑更加清楚,而且在编写自己的框架或者通用组件时非常好用。

9.1声明Proxy

new Proxy({},{});

第一个花括号相当于方法的主体,后边的花括号就是Proxy代理处理区域,相当于写钩子函数的地方。

9.2 get属性

get属性是在得到某对象属性值时预处理的方法,它接收三个参数:

target:得到的目标值

key:目标的key值,相当于对象的属性

property:这个不太常用

9.3 set属性

set属性是要改变Proxy属性值时,进行的预先处理。它接收四个参数:

target:目标值。

key:目标的Key值。

value:要改变的值。

receiver:改变前的原始值。

例:

let pro=new Proxy({
add:function(val){
return val+10;
},
name:'这是我的名字'
},{
get:function(target,key,property){
console.log('运行get');
return target[key];
},
set:function(target,key,value,receiver){
console.log('运行set');
return target[key]=value;
}
});
console.log(pro.name);
pro.name='新名字';
console.log(pro.name);

9.4 apply

apply是对方法的预处理

let target = function () {
return 'Hello';
};
var handler = {
apply(target, ctx, args) {
console.log('apply运行了');
return Reflect.apply(...arguments);
}
}
var pro = new Proxy(target, handler);
console.log(pro());

10 promise对象的使用

promise很好的解决了回调地狱的问题。

ES5的时候,在多层嵌套回调时,代码层次过多,很难进行维护和二次开发。

promise可以完美解决这个问题。

promise这个单词是“承诺”,当它成功时执行一些代码,当它失败时执行一些代码。它更符合人类的行为思考习惯。

promise执行多步操作非常好用。模仿一个多步操作的过程:

let state=1;
function step1(resolve,reject){
console.log('第一步:做饭');
if(state==1){
resolve('做饭完成');
}else{
reject('做饭失败');
}
}
function step2(resolve,reject){
console.log('第二步:吃饭');
if(state==1){
resolve('吃饭完成');
}else{
reject('吃饭失败');
}
}
function step3(resolve,reject){
console.log('第三步:洗碗');
if(state==1){
resolve('洗碗完成');
}else{
reject('洗碗失败');
}
} new Promise(step1).
then(function(val){
console.log(val);
return new Promise(step2);
}).
then(function(val){
console.log(val);
return new Promise(step3);
}).
then(function(val){
console.log(val);
return val
});

如果某一步出错:

promise可以让代码更加的结构化。在现在的开发中使用率算是最高的。

11 class类的使用

11.1类的声明

class Coder{
name(val){
console.log(val);
}
}
let me=new Coder;
me.name('你的名字');

当有多个方法时:

class Coder{
name(val){
return val;
}
skill(val){
console.log(this.name('张三')+'的技能是'+val);
}
}
let me=new Coder;
me.skill('web开发');

注意方法和方法中间不要写逗号,this指类本身。

11.2类的传参

用constructor( )进行传参。传递参数后可以直接使用this.xxx进行调用。

class Coder{
constructor(a,b){
this.a=a;
this.b=b;
}
add(){
return this.a+this.b;
}
}
let me=new Coder(1,2);
console.log(me.add());

11.3 class的继承

class Coder{
name(val){
console.log(val);
}
}
class Htmler extends Coder{ }
let me=new Htmler;
me.name('我是一个切图人员');

注意在写类的时候和ES5中的对象和构造函数要区分开,不要学混了。

12模块化操作

模块化操作主要包括两个方面:

export:模块的输出。

import:模块的引入。

谷歌浏览器地址栏中输入:

chrome://flags/,然后搜索javascript,把Experimental JavaScript设为启用:

引入js文件时,要加上type="module"

这样就可以直接预览效果了。

12.1 export的用法

export可以把变量,函数,对象进行模块化,提供外部调用接口,让外部进行引用。

12.1.1把一个变量模块化

temp.js:

export var a='abc';

index.js:

import {a} from './temp.js';
console.log(a);

index.html:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<script type="module" src="index.js"></script>
</body>
</html>

12.1.2多变量的输出

temp.js:

var a='aaa';
var b='bbb';
var c='ccc'; export {a,b,c}

index.js:

import {a,b,c} from './temp.js';
console.log(a,b,c);

12.1.3函数的模块化输出

temp.js:

export function test(a,b){
return a+b;
}

index.js:

import {test} from './temp.js';
console.log(test(10,20));

12.1.4 as的用法

有时候不想暴露模块里的变量名称,而给模块起一个更语义化的名称,可以使用as来操作。

temp.js:

var a='张三';
var b=18;
export {
a as name,
b as age
}

index.js:

import {name,age} from './temp.js';
console.log(name,age);

12.2 export和export default的区别

加上default相当于是一个默认的入口。在一个文件里export default只能有一个。

例1:写两个export:

temp.js:

export var a ='aaa';
export function add(a,b){
return a+b;
}

index.js:

import {a,add} from './temp.js';
console.log(a,add(10,20));

例2:export default

export default var a=12345';
import str from './temp';

这时import可以不写{},而且可以自定义命名。

(这里在chrome预览时报错,以后还是找个方式打包一下,等学完webpack再修改这里。)

总结

开发时尽量使用ES6语法,多用才熟练。如果生产环境不兼容,可以写完再用babel等工具转换。

最新文章

  1. java 对EXCEL表格的处理
  2. afx , afxMessageBox , MessageBox
  3. JS向光标指定位置插入内容
  4. jsp_属性范围_session
  5. 关于StartCoroutine的简单线程使用
  6. C#_abstract的用法
  7. Easy Problem-map和vector的使用
  8. Maven 依赖管理
  9. CSS Ruler 前端工具
  10. js sleep效果
  11. 一致性hash算法 - consistent hashing
  12. RPM vs SRPM
  13. jaxb xml to bean
  14. Android Studio rename module Can&#39;t rename root module
  15. IBATIS动态SQL(1)
  16. C/C++语言的语法基础
  17. 曝Wi-Fi重大缺陷:你浏览的或是个假网站
  18. Web 单点登录(SSO) 实现模型
  19. Uedit编辑器编辑Velocity
  20. English-英语学习杂志及资料

热门文章

  1. 《C语言深度解剖》学习笔记之预处理
  2. win10 uwp httpClient 登陆CSDN
  3. 用winrar和zip命令拷贝目录结构
  4. stl_tree.h/insert_unique()
  5. H3C PPP基本配置
  6. Python--day27--设计模式
  7. 2018-8-10-git-提交添加-emoij-文字
  8. SVN提示update更新成功,但是本地文件却没有更新
  9. C# 使用反射获取私有属性的方法
  10. 微信小程序之在线试题(1)