ES6 的强大功能!

  • 箭头函数
  • 模块
  • Promises 对象
  • 异步生成器 Generators
  • let以及const语法

let 跟 var 之间的差异1:

使用var声明变量,如重复声明,使后面的变量值会覆盖前面的变量值,而不会报错,这样会让我们调试变得非常困难,这在小型的项目也许不会发生,但是在大规模项目或代码规模量大的时候有可能会发生:

var myName = "Bob";
var myName = "Alice";
// 最终myName的值被更改为“Alice”

使用let,无法重复声明相同的变量名:

let myName = "Bob";
let myName = "Alice"; //报错!!!重复声明myName这个变量会报错

let 跟 var 之间的差异2:

let 跟 var 关键字作用相似,但是它们之间的某些特性不同:

  1. var声明的变量作用域是全局的,或是在函数块内的。
  2. let声明的变量作用域是在当前代码块,表达式或语句中。
for(var i =0;i < 3;i++) {
}
console.log(i); //控制台打印3,i 等于 3

这里的for循环块内的 i 是全局变量,类似于👇:

var i ;
for(i =0;i < 3;i++) {
}
console.log(i); //控制台打印3,i 等于 3

有种情况,当我们在for循环里的函数,使用了i变量,就会出现上面的情况:

var printNum;
for(var i =0;i < 3;i++) {
  if(i ==2){
      printNum = function(){
         console.log(i)
      }
   }
}
printNum(i); //控制台打印3,因为i等于 3

可以看到,控制台打印的是3,并不是2,因为,i是全局的,它随着for循环里的值变化而变化,当调用printNum函数时,打印的是循环内最终的值。

接下来,我们可以使用let,解决这个问题,得到想要的结果:

let printNum;
for(let i =0;i < 3;i++) {
  if(i ==2){
      printNum = function(){
         console.log(i)
      }
   }
}
printNum(i); //控制台打印2

上面这个例子,使用了let关键字,这样for循环里面的变量i的作用域就只在它里面而已,这样外部printNum函数保持了i为2的值,调用它就能打印出我们想要的结果。

我们再来看一个综合例子,加深对let的理解:

function checkCar() {
   "use strict"; //严格模式,用于检测代码错误或不安全的行为,如 pi = 3.14,少了声明的关键字,会报错!
  let car = "smallCar";
  if (true) {
    let  car= "bigCar";
    console.log("car 是: ", car);
  }
  console.log("car 是: ", car);
}
checkScope();
//控制台先后打印:
// car 是:bigCar
// car 是:smallCar

可以看到 if语块内的car,跟外部的car是没有任何关系的,都有各自的作用域,虽然使用let可以避免这样的错误,但是在实际编码中,尽量避免使用相同的变量名。

const与let的差异:

const 拥有let的所有优点,但const声明的变量是只读的,也就是说,声明后,不能再次进行修改:

const MY_KEY = "my Keys";
      MY_KEY = "not my keys"; //报错,不能修改!

const的使用场景一般用于不会再次修改的变量,通常称为常量,常量名为全部字母大写,不同字母用下划线分割,如我们在做数据持久化,通常需要指定它们的key,一般这样的值定义一次,不需要改动:

const USERNAME = "username";
localStorage.setItem(USERNAME,"Bob"); 

const声明的数组,元素值可以被更改:

const array = [8,9,10];
array = [1,2]; //报错
array[0] = 1; //array的8被修改为1
//array的值为:[1,9,10]

由此可见,const对于数组来说,只能保证常量名的指向不被更改,简单点来说就是不能直接用常量名赋予其它的值,但可以通过数组的索引对值更改。

Object.freeze保证对象的属性不被更改:

上面这个例子可以发现const并不能保证对象不被修改,这里ES6新增了一个Object.freeze()函数,能保证对象不被他人增、删、改,任何试图修改的操作都会被忽略:

let men = {
  name:"周杰伦",
  age:34
};
Object.freeze(men);
men.mother = "叶惠美"; // men 对象被冻结了,这个操作会被忽略
men.name = "张惠妹"; // 也会被忽略,不允许数据改变
console.log(obj); 
// { name: "周杰伦", age:34}

箭头函数:

优点: 简洁、优雅
使用场景:1、不考虑给函数命名 2、只需要传递参数 3、不考虑复用

当遇到这些场景,你都应该优先考虑使用它。

const today = () =>{
  return new Date();
}

当只需要返回一个值时,箭头函数允许你省略函数体和return:

const today = () =>  new Date();

你可以给箭头函数传递参数

const add = (x,y) =>{
  return x + y;
}
add(1,1) //return 2

给函数设置默认参数

通过给函数设置的参数设置默认值,能让我们的函数更加强大。

const greeting = function (name = "World"){
  console.log("Hello " + name);
}
greeting("Jim"); //打印 Hello Jim
greeting(); //打印Hello World

当没有给函数传入指定值的时候(也就是undefined),函数会使用默认提供的参数。

函数:剩余参数

通过使用剩余(rest)参数,可以更灵活的创建函数。通过它可以传递任意多个参数,而无需繁琐的定义它们。

function fruit(...args){
  console.log("I bought  " + args.length + "  fruit");
}
fruit("apple","banner","orange");
//打印 I bought  3  fruit

利用这特性我们还可以使用filter、map、reduce函数,操作这些参数。

//返回大于0的数
function greaterThanZero(...num){
  return num.filter((item) => item > 0);
}
console.log(greaterThanZero(-8,-1,-3,1,2,3));
//打印:[1, 2, 3]

展开操作符(spread),展开数组

通过展开操作符能够铺开数组和拷贝数组,请看栗子更容易理解:

let arr1 = [3,45,21];
console.log(Math.min(...arr1));
//打印:3

通过...arr1,把数组里面的参数一一列出,变为Math.min(3,45,21),所以得到我们想要的值。

下面通过展开操作符复制一个数组:

let arr1 = ["one","two","three","four","five"];
let arr2 = [...arr1];
//这样arr1里的值就被拷到arr2里边了,arr1里的值改变并不会影响到arr2

展开操作符只能用于数组中或者函数参数中,比如下面是错误的:

let arr = ["alert","error"];
let tip = ...arr; //报错

对象的解构赋值

对象的解构赋值非常强大,能够简单快速的取得变量和值。
例1:

let obj = {a:1,b:2,c:3};
const {a,b,c} = obj;
console.log(a,b,c);
//打印:123

例2:

let obj = {a:"one ",b:"two ",c:"three"};
const {a:x,b:y,c:z} = obj;
console.log(x,y,z);
//打印:one two three

例2的解构赋值,你可以理解为把a的值拷贝并交到x的手上

数组的解构

同样解构数组跟对象解构一样简单:

let myArr = [1,2,3,4,5];
const [a,b] = myArr;
//a = 1 , b=2

我们也可以利用剩余参数,获取剩余的值成为新的数组:

let myArr = [1,2,3,4,5];
const [a,b,...newArr] = myArr;
//a = 1 , b=2, newArr=[3,4,5]

把解构对象当做参数传入函数中

const shoppingList = {
  apple:5,
  jam:2,
  soy:4
}
function goShopping(list){
  let {apple,jam,soy} = list
}
//or 直接在写为函数参数
function goShopping({apple,jam,soy}){
  return "apple: "+ apple + ",jam: "+ jam + ",soy: "+soy;
}

看到了吗?它让程序变得更简洁,真的极其方便。

简洁的函数声明

在过去函数的声明是这样的:

let person = {
  name:"小明",
  hobby: function() {
  console.log(this.name + " 喜欢打篮球")
  }
}

在ES6中,定义函数不必书写function关键字和冒号:

let person = {
  name:"小明",
  hobby() {
  console.log(this.name + " 喜欢打篮球")
  }
}

ES6中 import 和 require 的差异

编写程序时常我们需要从外部引入代码或者函数,使用require,会让文件内的所有函数或变量全部导入,但往往我们只需要部分引入。

在es6中提高了非常便利的工具,import 可以只导入某个部分,这样就提高了程序的加载速度和内存空间。

//应用语法
import { 函数名 } from "文件路径"

export 导出可复用的代码块

export能导出文件里的函数或变量,从而使用import来导入到目标文件里使用。实现代码的重用。

const capitalizeString = (string) => {
  return string.charAt(0).toUpperCase() + string.slice(1);
}
export { capitalizeString } //导出函数。
export const place = "Beijing"; //导出变量。

or

const capitalizeString = (string) => {
  return string.charAt(0).toUpperCase() + string.slice(1);
}
const place = "Beijing"; //导出变量。
export { capitalizeString,place } //导出函数。

使用 * 导入所有内容

咱们还可以使用 import 导入文件里的所有内容。

//语法
import * as 名字(这是一个对象) from "文件地址"

//例子
import * as myMathModule from "math_functions";
myMathModule.add(2,3);
myMathModule.subtract(5,3);

你在import * as 后面定义的名字,它是一个对象,保存了导入文件里的所有内容,你可以使用这个对象的.语法来访问里面具体的内容。

用 export default 创建一个默认导出

刚刚我们学习了命名导出,但还有一个比较方便的默认导出,当只需要导出一个函数或值的时候,可以使用它,它常常用来给文件或模块创建返回值。

export default function subtract(x,y) {return x - y;}

导入一个默认导出

刚刚我们学习了一个默认导出,导入一个默认导出,跟之前的写法有些不同。

下面是从"math_functions"里导入一个默认导出的语法:

//减法
import subtract from "math_functions";
subtract(10,2);//返回8

在这里需要注意,导入一个默认导出,import 后面的名称不需要加花括号{}包围,你只需要在import之后写变量名即可。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 201,468评论 5 473
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,620评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,427评论 0 334
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,160评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,197评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,334评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,775评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,444评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,628评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,459评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,508评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,210评论 3 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,767评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,850评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,076评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,627评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,196评论 2 341

推荐阅读更多精彩内容

  • 第二回 【借用“冷”字,一人略出其大半】【雪芹平生所长】【脂斋取楽】【近时小说[《平山冷燕》]】【不识得既证之後】...
    瘦竹斋阅读 957评论 1 2
  • 今天是实训的第一天。今天主要完成了 java jdk安装与环境配置 mysql数据库安装与建立-- 导入book...
    michaeljimson阅读 186评论 0 0
  • 千盏灯房, 里边无数的灯火, 即使白天,也燃烧着。 明灭不定你, 是愿望? 是希望? 还是迷途的人儿的指路明灯?
    行者大饼阅读 95评论 0 2
  • 真的要买房么?或许你得先想想买房的目的,是投资,还是其他原因,比如学位,哄丈母娘,又或是房产带来的福利,比如户口,...
    Smile_小文阅读 544评论 9 3