你们好,本人名叫苏日俪格,你们叫我 (格格) 就好,最近我一直在研究ES6,在研究的过程当中并记录了下来,给你们分享下,有什么问题或者建议能够在评论区给出,望路过的大佬们不喜勿喷,本文仅供初入ES6江湖的人士(小白)专用,下面就让咱们来聊一聊ECMAScript:javascript
ECMAScript是一种由Ecma国际(前身为欧洲计算机制造商协会,英文名称是European Computer Manufacturers Association)经过ECMA-262标准化的脚本程序设计语言。这种语言在万维网上应用普遍,它每每被称为JavaScript或JScript,但实际上后二者是ECMA-262标准的实现和扩展。前端
综上所述咱们能够把ECMAScript当成是一个标准,而实现者是:JavaScript、typescript和actionscript;若是理解不了,就能够这么理解,好比HTML也是一个标准,而实现者是浏览器;vue
小白:以前有看到过ES2015,它又是什么意思呢?
格格:其实咱们一般所说的ES6也就是ES2015,意思就是在2015年发布的ECMAScript 6.0版本,而以后的ES2016和ES2017也都是ES6里面的,所以二者是同样的,只不过ES2015是官方的名称,java
下面让咱们来聊一聊ES6中的新特性吧:git
let和const都是定义(声明)用的,let是声明变量,而const是声明常量的;
变量:定义完了能够改变
常量:定义完了没法改变github
var虽然也是声明变量的,不过var声明有不少潜在的问题,至因而哪些问题,让咱们来看一个例子:web
for (var i=0; i<10; i++) { //coding } alert(i); // i=10
小白:⊙▽⊙这不科学啊,在外面还能访问?
格格:这个时候有的朋友看了就感受很神奇,尤为是学Java的,不该该是这样的对吧,但事实如此,接着往下看你就明白了typescript
若是非得说到做用域的问题的话,那么有两种做用域,一个是全局做用域,另外一个就是函数做用域(局部做用域),在这个例子里面声明的i就是一个全局的变量,因此下面是能够访问到的,若是下文继续使用i的话,那么就要从i=10开始,后果不堪设想。json
下面咱们再来看一个例子:小程序
var a = 1; function test(){ alert(a); // a = undefined var a = 2; } test();
这个例子暴露了一个问题,其实也不算是问题,就是由于JavaScript具备本身的特性:变量提高的问题(也能够叫作预解析),这究竟是个什么东西呢?上面的例子能够也当作是下面的例子:
var a = 1; function test(){ var a; alert(a); a = 2; } test();
相信你们已经看懂了,在代码执行的过程当中,事先定义了一个a,这时并无赋值,a固然就是undefined;
由此咱们给出一个定义:变量提高意思就是在js执行以前,会把变量提到顶部,并且不会突破做用域;再看一下预解析的例子:
<script type="text/javascript"> var a = 1; </script> <script type="text/javascript"> alert(a); // a = 1 </script>
JavaScript虽然是一个脚本语言,无需解析,可是它仍是有一个小小的预解析的过程:
读取一个script标签 ==> 预解析 ==> 执行代码 ==> 再读取下一个script标签 ==> ...依次循环
下面让咱们回到let和const:
for (let i=0; i<10; i++) { //coding... } alert(i); // i is not defined
你们能够看到,一样的例子使用let定义i的话,外面调用就会报错,那么这又是由于什么呢?
这就是ES6中引入的新特性:块级做用域
块级做用域就是{ coding... }
只要是带有{}的都是一个块级做用域,下面到了考察你们的时刻了:
let a = 1; function test(){ alert(a); let a = 2; } test();
和以前的例子同样,只不过将var换成了let,这个时候的结果就是a is not defined,由于let只在块级做用域中起做用,因此a不多是1,因为let不能提高,因此a就是未定义。
综上所述:let的第一个特性就是没有预解析,也不存在变量提高
小白:什么鬼?什么叫作第一个特性,难道还有第二个特性不成◔ ‸◔?
格格:那么我要在这里恭喜你中了大奖了,回家准备买彩票吧,它确实有第二个特性<( ̄ˇ ̄)/
下面在让咱们一块儿看一个例子:
let a = 1; let a = 2; alert(a);
这个时候你会发现,它和var是有着很是大的区别的,正常使用var的时候你们都知道,a确定是等于2的,那么在这里Identifier 'a' has already been declared,这句话的意思是a已经被定义了,也就是说let不容许重复定义同一个变量
格格:这就是它的第二个特性了,接来下咱们要讲的就是let的第三个特性ʅ(´◔౪◔)ʃ
小白:什么?o( ̄ヘ ̄o#) 还有第三个?
格格:其实第三个便是第二个,第二个便是第三个つ﹏⊂
下面咱们来看一个例子:
for (let i=0; i<10; i++) { let i = 2; console.log(i); }
小白:so easy!i已经被定义了呗
格格:嘿嘿,被忽悠了吧,答案是输出了10个2
小白:(・∀・*) 为啥子嘛
刚才说到,不容许重复定义一个变量,但它的条件确定是创建在块级做用域下的呀,这个循环中的i是做用域里面的i的父级,因此在里面仍是能够定义的,第三个特性就算是给第二个加个补充:在不一样做用域下,能够重复定义
小白:噢噢,刚才好像被晃了一会儿→_→
格格:ㄟ( ▔, ▔ )ㄏ
const的特性和let是如出一辙的,不一样的就只是常量而已,即为定义完了不能修改,不然报错
下面又到了考察你们的时刻了:
const arr = ['aaa','bbb','ccc']; arr.push('ddd'); console.log(arr); // ["aaa", "bbb", "ccc", "ddd"]
小白:说好的不能修改了?你在逗我。。。
格格:哈哈,你又不懂了吧
这个arr是一个数组,便是一个对象,对象自己是存在引用的,若是想让数组没法修改的话,也有办法的,能够用Object.freeze(对象)
格格:因此呀,var就当作是你的前任,忘了吧...
小白:哪能说忘就忘,相信本身会慢慢接受现任的
当我第一次听到这个东西的时候,内心冒出了无数的疑问,这个名字太奇怪了,可是我想说的是解构赋值很是有用
当咱们定义多个变量的时候还要一个一个去命名和赋值,很是麻烦,若是用了解构赋值,像这样:
let [a,b,c] = [1,2,3]; console.log(a,b,c); // 1,2,3
正如你所看到的,它默认的把你右边赋的值都解出来分配给左边的变量,一一对应进行赋值
小白:这个看起来很好用,但是若是两侧不对称了呢?
格格:解构赋值意思就是说两侧的结构和格式都必须如出一辙,再举个例子:
let [a,b,c] = [1,[2,3]]; console.log(a,b,c); // 1 [2, 3] undefined
两侧不一致就会致使像上面这样的结果,解决方式就是:
let [a,[b,c]] = [1,[2,3]]; console.log(a,b,c); // 1 2 3
数组还有一种玩法就是:
let [a,b,c='暂无数据'] = [1,2]; console.log(a,b,c); // 1 2 暂无数据
固然上面这种写法用处不大,可是在交换两个变量的值的时候,正常是还得找第三个变量打配合就行转换,如今不须要了:
let a = 1; let b = 2; [a,b] = [b,a]; console.log(a,b); // 2 1
以上这是数组的解构赋值,下面看一下json的解构赋值是怎样的:
let {name,age,job} = { name: '苏日俪格', age: 24, job: 'web前端开发' }
解构赋值通常用在和后台进行数据交互的时候,后台数据大多都是json形式的传递的,数据多的时候都是json嵌套json,以致于有不少,这时就能够用解构赋值全都解出来就能够了,不要谢我,记住我是雷锋~( ̄▽ ̄~)(~ ̄▽ ̄)~
let json = { name: '苏日俪格', age: '24', job: 'web前端开发' } let {name,age,job} = json; console.log(name,age,job); // 苏日俪格 24 web前端开发
还有第二种写法:
let json = { name: '苏日俪格', age: '24', job: 'web前端开发' } let {name:a,age:b,job:c} = json; console.log(a,b,c); // 苏日俪格 24 web前端开发
从字面就可以理解,上面这种写法只是给每个变量起了一个名字,可是若是起了名字以后,下面调用的时候里面的参数仍是写的之前名字,那么就会报错is not defined
接下来给你们讲一个关于解构赋值的小小的应用:
function getPos(){ return { l: 10, t: 20 } } let {l, t} = getPos(); console.log(l,t); // 10 20
固然解构赋值也能够做为参数进行传递,用法都是同样的,保持一一对应便可。
讲到这里,给你们插一个小tip,在ES2017 6月发布的版本中新增了一个小可爱:
function show(a,b,c){ console.log(a,b,c); // 1 2 3 } show(1,2,3,);
仔细看会发现咱们在传值的时候,多传了一个逗号(,),可是数据依然可以显示出来,这个看似没用,可是在与后台交互的时候,每每会由于多了个逗号而致使程序报错;不知道你们有没有作过微信小程序,里面有个配置文件app.json,是用来配置整个小程序全部的页面的,当咱们想把另外一个做为首页访问的话,还要特地去删掉那个多余的逗号,这个解决了咱们遇到的问题。
字符串模板其实就是为了下降字符串拼接难度而生的,在拼接一些数据量大的时候,这个可真的是让人头疼的要死,好比说:
let name = '苏日俪格'; let age = 24; let str = '个人名字叫'+name+',今年'+age+'岁'; console.log(str); // 个人名字叫苏日俪格,今年24岁
拼接起来很麻烦,数据多的话就容易乱,ES6提出了这个字符串模板中有一个(``)
小白:这个字符是怎么打出来的呢?
格格:切换成英文输入法,找到键盘上的数字1键前面的那个按键,记住不是小键盘数字1哦
使用反引号(``)拼接是这样的:
let name = '苏日俪格'; let age = 24; let str = `个人名字叫${name},今年${age}岁`; console.log(str); // 个人名字叫苏日俪格,今年24岁
格格:这样看起来是否是清晰的不要不要的?
还有字符串新增的方法,好比说str.startsWith(要检测的东西);
这个通常用来检测协议(http/https),返回布尔值;既然有以谁开头了那么就有以谁结尾:str.endsWith(要检测的东西);
这个通常用来检测文件类型(jpg);重复字符串方法:str.repeat(次数);
这个方法能够将一个字符串重复输出,通常不会用到,造假数据可能会用到吧
在箭头函数以前,须要看一个例子:
function show(a=1){ let a = 2; console.log(a); // Identifier 'a' has already been declared } show();
上面的代码告诉咱们函数的参数默认已经被定义了,一经声明,就不能再用let或者const进行声明了,只能用var;这个有点跑题了,算是送你们的一个小tip吧,下面让咱们一块儿来看箭头函数吧:
//普通函数的写法: function show(){ return 1; } show();
//上面的函数的箭头函数写法: let show = () => 1; // 箭头的左边是参数右边是返回值 console.log(show());
若是要想在函数里面写语句的时候,写法是这样的:
let show = (a=1,b=2) => { console.log(a,b); // 1 2 } show();
箭头函数和普通函数除了写法不一样以外,还有三点不一样,请看下面的例子:
let json = { name: '苏日俪格', show: function(){ setTimeout(function(){ console.log(this.name); // 控制台什么都没有输出 },1000); } } json.show();
这个例子大多都是在vue等框架下开发遇到的问题,由于this指向的是当前的函数,先要让它指向外面的json对象,就还要在外面进行转换,太麻烦,而箭头函数则不一样:
let json = { name: '苏日俪格', show: function(){ setTimeout(() => { console.log(this.name); // 苏日俪格 },1000); } } json.show();
综上所述,第一个不一样之处就是箭头函数里的this指向的是定义函数所在的对象,而不是运行时所在的对象
小白:那第二个不一样之处呢?
格格:第二个就是箭头函数里面不能使用arguments,若是用了就是is not defined
解决办法:就是...扩展运算符(在本章的第五小节)
let show = (...a) => { console.log(a); // [1, 2, 3, 4, 5] }; show(1,2,3,4,5);
第三个就是箭头函数不能当作构造函数来用:
let Show = ()=>{ this.name = '苏日俪格'; } let a = new Show(); console.log(a.name); // Show is not a constructor
...
表明着扩展运算符或Rest(剩余)运算符
废话很少说,直接带你们看几个例子:
// 当传入的参数不肯定或者多个的时候,就能够当作arguments来使用 function show(...a){ console.log(a); // [14, 12, 54, 33, 22] } show(14,12,54,33,22);
此外扩展运算符还能够解决数组的引用的问题:
let a = [14,12,54,33,22]; let b = a; // 至关于copy a.push(44); console.log(a); // [14, 12, 54, 33, 22, 44] console.log(b); // [14, 12, 54, 33, 22, 44]
上面这个例子说明了b是a的一个引用,也就是说两者所在的内存是同一个,要想改变a不影响b的话,就要开辟一个新内存,解决方式:
let a = [14,12,54,33,22]; let b = [...a]; a.push(44); console.log(a); // [14, 12, 54, 33, 22, 44] console.log(b); // [14, 12, 54, 33, 22]
扩展运算符还能够用来数组的排序,此排序并非什么大小排序,而是按照每一位的首位数字进行排序的,第一位相同就看第二位,依次排列,和字典式排序类似,看下面的例子:
function orderBy(...a){ return a.sort(); } console.log(orderBy(51,12,7,34,3)); // [12, 3, 34, 51, 7]
let arr = ['aaa','bbb','ccc']; let arr2 = "aabbcc"; console.log(arr); // ["aaa", "bbb", "ccc"] console.log(...arr); // aaa bbb ccc console.log(arr2); // aabbcc console.log(...arr2); // a a b b c c
综上所述,...能够完成字符串和数组之间的转换
小白:那个Rest运算符又是什么呢?
请看下面的这个例子:
function show(a,...b){ console.log(a); // 51 console.log(b); // [12, 7, 34, 3] } show(51,12,7,34,3);
看完了这个例子懂了吧,就是说前面的参数一一对应,后面的那个...b就表明剩下的参数,由于是剩余参数因此这个剩余运算符要放在最后的位置,所以有的人又称为剩余运算符
本文的全部内容均是一字一字敲上去的,但愿你们阅读完本文能够有所收获,由于能力有限,掌握的知识也是不够全面,欢迎你们提出来一块儿分享!谢谢O(∩_∩)O~