编程知识 cdmana.com

现代JavaScript—ES6+中的Imports,Exports,Let,Const和Promise

转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。
原文出处:https://www.freecodecamp.org/news/learn-modern-javascript/

 

在过去几年里,JavaScript有很多的更新。如果你想提升写代码的能力,这些更新将会对你有非常大的帮助。

对于程序员来说,了解这门语言的最新发展是非常重要的。它能使你跟上最新趋势,提高代码质量,在工作中出类拔萃,从而进一步提升你的薪资待遇。

特别地,如果你想学习像React、 Angular或Vue这样的框架,你必须掌握这些最新的特性。

最近,JavaScript增加了许多有用的功能,比如Nullish coalescing operator, optional chaining, Promises, async/await, ES6 destructuring,等等。

那么现在,我们将探讨每个JavaScript开发者都应该知道的概念。

 

JavaScript中的Letconst

 

在ES6之前,JavaScript使用var关键字来声明变量,var只有全局作用域和函数作用域,所谓全局作用域就是在代码的任何位置都能访问var声明的变量,而函数作用域在变量声明的当前函数内部访问变量。此时是没有块级作用域的。

随着let和const这两个关键字的添加,JS增加了块级作用域的概念。

如何在JavaScript中使用let

当我们在用let声明变量时,用于声明一次之后就不能再以相同的名称重新声明它。

1
2
3
4
5
6
7
8
9
// ES5 Code
var   value = 10;
console.log(value);  // 10
 
var   value =  "hello" ;
console.log(value);  // hello
 
var   value = 30;
console.log(value);  // 30

如上所示,我们多次使用var关键字重新声明了变量值。

在ES6之前,我们可以使用var重新声明之前已经声明过的变量,这就会导致了一个问题:如果我们在不知情的情况下,在其他地方重新声明了该变量,很有可能会覆盖原先变量的值,造成一些难以调试的问题。

所以,Let解决很好地解决此问题。当你使用let重新声明变量值时,将会报错。

1
2
3
4
5
6
7
8
9
10
11
12
13
// ES6 Code
let   value = 10;
console.log(value);  // 10
 
let   value =  "hello" ;  // Uncaught SyntaxError: Identifier 'value' has already been declared
 
但是,以下代码是合法的:
// ES6 Code
let   value = 10;
console.log(value);  // 10
 
value =  "hello" ;
console.log(value);  // hello

我们发现上面的代码看起来没什么问题,是因为我们重新给value变量赋了一个新值,但是并没有重新声明。

我们来看下下面的代码:

1
2
3
4
5
6
7
// ES5 Code
var   isValid =  true ;
if (isValid) {
   var   number = 10;
   console.log( 'inside:' , number);  // inside: 10
}
console.log( 'outside:' , number);  // outside: 10

如上所示,在使用var声明变量时,可以在if块之外访问该变量。

而使用let声明的number变量只能在if块内访问,如果在if块外访问将会报错。

我们来看下接下来的代码

1
2
3
4
5
6
7
// ES6 Code
let   isValid =  true ;
if (isValid) {
   let   number = 10;
   console.log( 'inside:' , number);  // inside: 10
}
console.log( 'outside:' , number);  // Uncaught ReferenceError: number is not defined

如上述代码所示,使用let分别在if块内、if块外声明了number变量。在if块外,number无法被访问,因此会出现引用错误。

但是,如果变量number在if块外已经声明,将会出现下面的结果。

1
2
3
4
5
6
7
8
9
10
// ES6 Code
let   isValid =  true ;
let   number = 20;
 
if (isValid) {
   let   number = 10;
   console.log( 'inside:' , number);  // inside: 10
}
 
console.log( 'outside:' , number);  // outside: 20

现在在单独的范围内有两个number变量。在if块外,number的值为20。

1
2
3
4
5
// ES5 Code
for ( var   i = 0; i < 10; i++){
  console.log(i);
}
console.log( 'outside:' , i);  // 10

当使用var关键字时,i在 for循环之外也可以访问到。

 

1
2
3
4
5
6
// ES6 Code
for ( let   i = 0; i < 10; i++){
  console.log(i);
}
 
console.log( 'outside:' , i);  // Uncaught ReferenceError: i is not defined

而使用let关键字时,在for循环外部是不可访问的。

因此,正如上述示例代码所示,let声明的变量只能在块内部可用,而在块外部不可访问。

我们可以使用一对大括号创建一个块,如下:

1
2
3
4
5
6
7
8
9
let   i = 10;
{
  let   i = 20;
  console.log( 'inside:' , i);  // inside: 20
  i = 30;
  console.log( 'i again:' , i);  // i again: 30
}
 
console.log( 'outside:' , i);  // outside: 10

 

前面有提到,let在同一个块中不能重新声明变量,不过可以在另一个块中重新声明。如上代码所示,我们在块内重新声明了i,并赋值20,该变量仅可在该块中使用。

在块外,当我们打印变量时,我们得到的是10而不是之前分配的值,这是因为块外,内部变变量i是不存在的。

如果在块外未声明变量,那么将会报错:

1
2
3
4
5
6
7
8
{
  let   i = 20;
  console.log( 'inside:' , i);  // inside: 20
  i = 30;
  console.log( 'i again:' , i);  // i again: 30
}
 
console.log( 'outside:' , i);  // Uncaught ReferenceError: i is not defined

 

如何在JavaScript使用const

const关键字在块级作用域中的工作方式与let关键字完全相同。因此,我们来看下他们的区别。

const声明的变量为常量,其值是不能改变的。而let声明的变量,可以为其赋一个新值,如下所示:

1
2
3
let   number = 10;
number = 20;
console.log(number);  // 20
但是以下情况,我们不能这样使用const
1
2
const number = 10;
number = 20;  // Uncaught TypeError: Assignment to constant variable.

我们甚至不能使用const像下面一样重新声明。

1
2
3
4
const number = 20;
console.log(number);  // 20
 
const number = 10;  // Uncaught SyntaxError: Identifier 'number' has already been declared

现在,看下面的代码:

1
2
3
const arr = [1, 2, 3, 4];
arr.push(5);
console.log(arr);  // [1, 2, 3, 4, 5]

我们说过const声明的常量,它的值永远不会改变——但是我们改变了上面的常量数组并没有报错。这是为什么呢?

注意:数组是引用类型,而不是JavaScript的基本类型

实际存储在arr中的不是数组,而是数组存储的内存位置的引用(地址)。执行arr.push(5),并没有改变arr指向的引用,而是改变了存储在那个引用上的值。

对象也是如此:

1
2
3
4
5
6
7
8
const obj = {
  name:  'David' ,
  age: 30
};
 
obj.age = 40;
 
console.log(obj);  // { name: 'David', age: 40 }

 

这里,我们也没有改变obj指向的引用,而是改变了存储在引用的值。

因此,上述的代码将会起作用,但下面的代码是无效的。

1
2
3
const obj = { name:  'David' , age: 30 };
const obj1 = { name:  'Mike' , age: 40 };
obj = obj1;  // Uncaught TypeError: Assignment to constant variable.

这样写会抛出异常,因为我们试图更改const变量指向的引用。

因此,在使用const时要记住一点:使用const声明常量时,不能重新声明,也不能重新赋值。如果声明的常量是引用类型,我们可以更改存储在引用的值。

同理,下面的代码也是无效的。

1
2
const arr = [1, 2, 3, 4];
arr = [10, 20, 30];  // Uncaught TypeError: Assignment to constant variable.

  

总结:

  • 关键字let和const在JavaScript中添加块级作用域。
  • 当我们将一个变量声明为let时,我们不能在同一作用域(函数或块级作用域)中重新定义或重新声明另一个具有相同名称的let变量,但是我们可以重新赋值。
  • 当我们将一个变量声明为const时,我们不能在同一作用域(函数或块级作用域)中重新定义或重新声明具有相同名称的另一个const变量。但是,如果变量是引用类型(如数组或对象),我们可以更改存储在该变量中的值。

好了,我们继续下一个话题: promises。

 

JavaScript中的promises

 

对于很多新开发者来说,promises是JavaScript中较难理解的部分。ES6中原生提供了Promise对象,那么Promise究竟是什么呢?

Promise 对象代表了未来将要发生的事件,用来传递异步操作的消息。

如何创造一个promise

使用promise构造函数创建一个promise,如下所示:

1
2
3
const promise =  new   Promise( function (resolve, reject) {
  
});

Promise的构造函数接收一个函数作为参数,并且在内部接收两个参数:resolve,reject。 resolve和reject参数实际上是我们可以调用的函数,具体取决于异步操作的结果。

Promise 有三种状态:

  • pending: 初始状态,不是成功或失败状态。
  • fulfilled:表示操作成功完成。
  • rejected: 表示操作失败。

当我们创建Promise时,它处于等待的状态。当我们调用resolve函数时,它将进入已完成状态。如果调用reject,他将进入被拒绝状态。

在下面的代码中,我们执行了一个异步操作,也就是setTimeout,2秒后,调用resolve方法。

 

1
2
3
4
5
6
const promise =  new   Promise( function (resolve, reject) {
  setTimeout( function () {
   const sum = 4 + 5;
   resolve(sum);
  }, 2000);
});

我们需要使用以下方法注册一个回调.then获得1promise执行成功的结果,如下所示:

1
2
3
4
5
6
7
8
9
10
const promise =  new   Promise( function (resolve, reject) {
  setTimeout( function () {
   const sum = 4 + 5;
   resolve(sum);
  }, 2000);
});
 
promise.then( function (result) {
  console.log(result);  // 9
});

then接收一个参数,是函数,并且会拿到我们在promise中调用resolve时传的的参数。

如果操作不成功,则调用reject函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const promise =  new   Promise( function (resolve, reject) {
  setTimeout( function () {
   const sum = 4 + 5 +  'a' ;
   if (isNaN(sum)) {
     reject( 'Error while calculating sum.' );
   }  else   {
     resolve(sum);
   }
  }, 2000);
});
 
promise.then( function (result) {
  console.log(result);
});

如果sum不是一个数字,那么我们调用带有错误信息的reject函数,否则我们调用resolve函数。

执行上述代码,输出如下:

 

 

 

调用reject函数会抛出一个错误,但是我们没有添加用于捕获错误的代码。

需要调用catch方法指定的回调函数来捕获并处理这个错误。

1
2
3
4
5
promise.then( function (result) {
  console.log(result);
}). catch ( function (error) {
  console.log(error);
});

输出如下:

 

 

 

所以建议大家在使用promise时加上catch方法,以此来避免程序因错误而停止运行。

链式操作

我们可以向单个promise添加多个then方法,如下所示:

1
2
3
4
5
6
7
8
9
promise.then( function (result) {
  console.log( 'first .then handler' );
  return   result;
}).then( function (result) {
  console.log( 'second .then handler' );
  console.log(result);
}). catch ( function (error) {
  console.log(error);
});

当添加多个then方法时,前一个then方法的返回值将自动传递给下一个then方法。

 

 

如上图所示,我们在第一个then方法中输出字符串,并将接收的参数result(sum)返回给下一个result。

在下一个then方法中,输出字符串,并输出上一个then方法传递给它的result。

如何在JavaScript中延迟promise的执行

很多时候,我们不希望立即创建promise,而是希望在某个操作完成后再创建。

我们可以将promise封装在一个函数中,然后从函数中返回promise,如下所示:

 

1
2
3
4
5
6
7
8
9
10
11
12
function   createPromise() {
  return   new   Promise( function (resolve, reject) {
   setTimeout( function () {
    const sum = 4 + 5;
    if (isNaN(sum)) {
      reject( 'Error while calculating sum.' );
    }  else   {
     resolve(sum);
    }
   }, 2000);
  });
}

这样,我们就可以通过函数将参数传递给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
function   createPromise(a, b) {
  return   new   Promise( function (resolve, reject) {
   setTimeout( function () {
    const sum = a + b;
    if (isNaN(sum)) {
      reject( 'Error while calculating sum.' );
    }  else   {
     resolve(sum);
    }
   }, 2000);
  });
}
 
createPromise(1,8)
  .then( function (output) {
   console.log(output);  // 9
});
 
// OR
 
createPromise(10,24)
  .then( function (output) {
   console.log(output);  // 34
});

 

 

 

此外,我们只能向resolve或reject函数传递一个值。如果你想传递多个值到resolve函数,可以将它作为一个对象传递,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const promise =  new   Promise( function (resolve, reject) {
  setTimeout( function () {
   const sum = 4 + 5;
   resolve({
    a: 4,
    b: 5,
    sum
   });
  }, 2000);
});
 
promise.then( function (result) {
  console.log(result);
}). catch ( function (error) {
  console.log(error);
});

 

 

 

如何在JavaScript中使用箭头函数

上述示例代码中,我们使用常规的ES5语法创建了promise。但是,通常使用箭头函数代替ES5语法,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const promise =  new   Promise((resolve, reject) => {
  setTimeout(() => {
   const sum = 4 + 5 +  'a' ;
   if (isNaN(sum)) {
     reject( 'Error while calculating sum.' );
   }  else   {
     resolve(sum);
   }
  }, 2000);
});
 
promise.then((result) => {
  console.log(result);
});

你可以根据自己需要使用ES5或ES6语法。

 

ES6 Import 和Export 语法

在ES6之前,我们在一个HTML文件中可以使用多个script标签来引用不同的JavaScript文件,如下所示:

1
2
3
<script type= "text/javascript"   src= "home.js" ></script>
<script type= "text/javascript"   src= "profile.js" ></script>
<script type= "text/javascript"   src= "user.js" ></script>

但是如果我们在不同的JavaScript文件中有一个同名的变量,将会出现命名冲突,你实际得到的可能并不是你期望的值。

ES6增加了模块的概念来解决这个问题。

在ES6中,我们编写的每一个JavaScript文件都被称为模块。我们在每个文件中声明的变量和函数不能用于其他文件,除非我们将它们从该文件中导出并、在另一个文件中得到引用。

因此,在文件中定义的函数和变量是每个文件私有的,在导出它们之前,不能在文件外部访问它们。

export有两种类型:

  • 命名导出:在一个文件中可以有多个命名导出
  • 默认导出:单个文件中只能有一个默认导出

JavaScript中的命名导出

如下所示,将单个变量命名导出:

1
export   const temp =  "This is some dummy text" ;

如果想导出多个变量,可以使用大括号指定要输出的一组变量。

1
2
3
const temp1 =  "This is some dummy text1" ;
const temp2 =  "This is some dummy text2" ;
export   { temp1, temp2 };
需要注意的是,导出语法不是对象语法。因此,在ES6中,不能使用键值对的形式导出。
1
2
   // This is invalid syntax of export in ES6
export   { key1: value1, key2: value2 }
import命令接受一对大括号,里面指定要从其他模块导入的变量名。
1
import   { temp1, temp2 } from  './filename' ;

注意,不需要在文件名中添加.js扩展名,因为默认情况下会考虑该拓展名。

1
2
3
4
// import from functions.js file from current directory
import   { temp1, temp2 } from  './functions' ;
           // import from functions.js file from parent of current directory
import   { temp1 } from  '../functions' ;

提示一点,导入的变量名必须与被导入模块对外接口的名称相同。

因此,导出应使用:

1
2
// constants.js
export   const PI = 3.14159;

那么在导入的时候,必须使用与导出时相同的名称:

1
import   { PI } from  './constants' ;

// This will throw an error

1
import   { PiValue } from  './constants' ;

如果想为输入的变量重新命名,可以使用as关键字,语法如下:

1
import   { PI as PIValue } from  './constants' ;

我们以为PI重命名为PIValue,因此不能再使用PI变量名。

 

导出时也可使用下面的重命名语法:  

1
2
3
// constants.js
const PI = 3.14159;
export   { PI as PIValue };

  

然后在导入是,必须使用PIValue。

1
import   { PIValue } from  './constants' ;

命名导出某些内容之前必须先声明它。

1
2
3
4
export   'hello' ;  // this will result in error
export   const greeting =  'hello' ;  // this will work
export   { name:  'David'   };  // This will result in error
export   const object = { name:  'David'   };  // This will work

我们来看下面的validations.js 文件:  

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
// utils/validations.js
 
const isValidEmail =  function (email) {
   if   (/^[^@ ]+@[^@ ]+\.[^@ \.]{2,}$/.test(email)) {
     return   "email is valid" ;
   }  else   {
     return   "email is invalid" ;
   }
};
 
const isValidPhone =  function (phone) {
   if   (/^[\\(]\d{3}[\\)]\s\d{3}-\d{4}$/.test(phone)) {
     return   "phone number is valid" ;
   }  else   {
     return   "phone number is invalid" ;
   }
};
 
function   isEmpty(value) {
   if   (/^\s*$/.test(value)) {
     return   "string is empty or contains only spaces" ;
   }  else   {
     return   "string is not empty and does not contain spaces" ;
   }
}
 
export   { isValidEmail, isValidPhone, isEmpty };

在index.js中,我们可以使用如下函数:

1
2
3
4
5
6
7
8
// index.js
import   { isEmpty, isValidEmail } from  "./utils/validations" ;
 
console.log( "isEmpty:" , isEmpty( "abcd" ));  // isEmpty: string is not empty and does not contain spaces
 
console.log( "isValidEmail:" , isValidEmail( "abc@11gmail.com" ));  // isValidEmail: email is valid
 
console.log( "isValidEmail:" , isValidEmail( "ab@c@11gmail.com" ));  // isValidEmail: email is invalid

JavaScript的默认导出

如上所述,单个文件中最多只能有一个默认导出。但是,你可以在一个文件中使用多个命名导出和一个默认导出。

要声明一个默认导出,我们需要使用以下语法:

1
2
3
//constants.js
const name =  'David' ;
export   default   name;

在导入时就不需要再使用花括号了。  

1
import   name from  './constants' ;

  

如下,我们有多个命名导出和一个默认导出:

1
2
3
4
5
6
// constants.js
export   const PI = 3.14159;
export   const AGE = 30;
 
const NAME =  "David" ;
export   default   NAME;

  

此时我们使用import导入时,只需要在大括号之前指定默认导出的变量名。

1
2
// NAME is default export and PI and AGE are named exports here
import   NAME, { PI, AGE } from  './constants' ;

使用 export default 导出的内容,在导入的时候,import后面的名称可以是任意的。

1
2
3
4
5
6
// constants.js
const AGE = 30;
export   default   AGE;
 
import   myAge from ‘./constants’;
console.log(myAge);  // 30

另外, export default的变量名称从Age到myAge之所以可行,是因为只能存在一个export default。因此你可以随意命名。还需注意的是,关键字不能在声明变量之前。

1
2
// constants.js
export   default   const AGE = 30;  // This is an error and will not work

因此,我们需要在单独的一行使用关键字。

1
2
3
// constants.js
const AGE = 30;
export   default   AGE;

  

不过以下形式是允许的:

1
2
3
4
5
//constants.js
export   default   {
  name:  "Billy" ,
  age: 40
};

并且需要在另一个文件中使用它

1
2
3
import   user from  './constants' ;
console.log(user.name);  // Billy
console.log(user.age);  // 40

  

还有,可以使用以下语法来导入constants.js文件中导出的所有变量:

1
2
// test.js
import   * as constants from  './constants' ;

 

下面,我们将导入所有我们constants.js存储在constants变量中的命名和export default。因此,constants现在将成为对象。

1
2
3
4
5
6
// constants.js
export   const USERNAME =  "David" ;
export   default   {
  name:  "Billy" ,
  age: 40
};

在另一个文件中,我们按一下方式使用。

1
2
3
4
5
6
7
// test.js
 
import   * as constants from  './constants' ;
 
console.log(constants.USERNAME);  // David
console.log(constants. default );  // { name: "Billy", age: 40 }
console.log(constants. default .age);  // 40

也可以使用以下方式组合使用命名导出和默认导出:

1
2
3
4
5
6
7
8
9
10
// constants.js
const PI = 3.14159; const AGE = 30;
const USERNAME =  "David" ;
const USER = {
  name:  "Billy" ,
  age: 40
};
export   { PI, AGE, USERNAME, USER as  default   };
 
import   USER, { PI, AGE, USERNAME } from  "./constants" ;

总而言之:

ES6中,一个模块就是一个独立的文件,该文件内部的所有变量,外部都无法获取。如果想从外部读取模块内的某个变量,必须使用export关键字导出该变量,使用import关键字导入该变量。

 

JavaScript中的默认参数

ES6增加了一个非常有用的特性,即在定义函数时提供默认参数。

假设我们有一个应用程序,一旦用户登录系统,我们将向他们显示一条欢迎消息,如下所示:

1
2
3
4
function   showMessage(firstName) {
   return   "Welcome back, "   + firstName;
}
console.log(showMessage( 'John' ));  // Welcome back, John

但是,如果数据库中没有用户名,那该怎么办呢?所以,我们首先需要检查是否提供了firstName,然后再显示相应的信息。

在ES6之前,我们必须写这样的代码:  

1
2
3
4
5
6
7
8
9
10
function   showMessage(firstName) {
   if (firstName) {
     return   "Welcome back, "   + firstName;
   }  else   {
     return   "Welcome back, Guest" ;
   }
}
 
console.log(showMessage( 'John' ));  // Welcome back, John
console.log(showMessage());  // Welcome back, Guest

但现在使用ES6提供的默认参数,我们可以这样写:

1
2
3
4
5
6
function   showMessage(firstName =  'Guest' ) {
    return   "Welcome back, "   + firstName;
}
 
console.log(showMessage( 'John' ));  // Welcome back, John
console.log(showMessage());  // Welcome back, Guest

函数的默认参数可以为任意值。

1
2
3
4
5
6
7
8
function   display(a = 10, b = 20, c = b) {
  console.log(a, b, c);
}
 
display();  // 10 20 20
display(40);  // 40 20 20
display(1, 70);  // 1 70 70
display(1, 30, 70);  // 1 30 70

在上面的代码中,我们没有提供函数的所有参数,实际代码等同于:

1
2
3
display();  // 等同于display(undefined, undefined, undefined)
display(40); 等同于display(40, undefined, undefined)
display(1, 70); 等同于display(1, 70, undefined)

因此,如果传递的参数是undefined,则对应的参数将使用默认值。

我们还可以将对象或计算值指定为默认值,如下:

1
2
3
4
5
const defaultUser = {
   name:  'Jane' ,
   location:  'NY' ,
   job:  'Software Developer'
};

const display = (user = defaultUser, age = 60 / 2 ) => {

 console.log(user, age);

};

display();

 

/* output

 

{

  name: 'Jane',

  location: 'NY',

  job: 'Software Developer'

} 30

*/

  

ES5代码如下:

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
// ES5 Code
function   getUsers(page, results, gender, nationality) {
   var   params =  "" ;
   if (page === 0 || page) {
    params += `page=${page}&`;
   }
   if (results) {
    params += `results=${results}&`;
   }
   if (gender) {
    params += `gender=${gender}&`;
   }
   if (nationality) {
    params += `nationality=${nationality}`;
   }
 
   fetch( 'https://randomuser.me/api/?'   + params)
    .then( function (response) {
      return   response.json();
    })
    .then( function (result) {
     console.log(result);
    })
    . catch ( function (error) {
      console.log( 'error' , error);
    });
}
 
getUsers(0, 10,  'male' ,  'us' );

  

在这段代码中,我们通过在getUsers函数中传递各种可选参数来进行API调用。在进行API调用之前,我们添加了各种if条件来检查是否添加了参数,并基于此构造查询字符串,如下所示:

https://randomuser.me/api/? page=0&results=10&gender=male&nationality=us

 

使用ES6的默认参数则不必添这么多if条件,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
function   getUsers(page = 0, results = 10, gender =  'male' ,nationality =  'us' ) {
  fetch(`https: //randomuser.me/api/?page=${page}&results=${results}&gender=${gender}&nationality=${nationality}`)
  .then( function (response) {
   return   response.json();
  })
  .then( function (result) {
    console.log(result);
  })
  . catch ( function (error) {
   console.log( 'error' , error);
   });
}
getUsers();

这样一来,代码得到了大量的简化,即便我们不为getUsers函数提供任何参数时,它也能采用默认值。当然,我们也可以传递自己的参数:

1
getUsers(1, 20,  'female' ,  'gb' );

它将覆盖函数的默认参数。

null不等于未定义

注意: 定义默认参数时,null和undefined是不同的。

我们来看下面的代码:

1
2
3
4
5
6
7
8
function   display(name =  'David' , age = 35, location =  'NY' ){
  console.log(name, age, location);
}
display( 'David' , 35);  // David 35 NY
display( 'David' , 35, undefined);  // David 35 NY
// OR
display( 'David' , 35, undefined);  // David 35 NY
display( 'David' , 35,  null );  // David 35 null
当我们传递null作为参数时,它实际是给location参数赋一个空值,与undefined不一样。所以它不会取默认值“NY”。

Array.prototype.includes

ES7增加了数组的includes方法,用来判断一个数组是否包含一个指定的值,如果是返回 true,否则false
1
2
3
4
// ES5 Code
const numbers = [ "one" ,  "two" ,  "three" ,  "four" ];
console.log(numbers.indexOf( "one" ) > -1);  // true
console.log(numbers.indexOf( "five" ) > -1);  // false

数组可以使用includes方法:

1
2
3
4
// ES7 Code
const numbers = [ "one" ,  "two" ,  "three" ,  "four" ];
console.log(numbers.includes( "one" ));  // true
console.log(numbers.includes( "five" ));  // false
includes方法可以使代码简短且易于理解,它也可用于比较不同的值。
1
2
3
4
5
6
7
8
9
10
const day =  "monday" ;
if (day ===  "monday"   || day ===  "tuesday"   || day ===  "wednesday" ) {
   // do something
}
 
// 以上代码使用include方法可以简化如下:
const day =  "monday" ;
if ([ "monday" ,  "tuesday" ,  "wednesday" ].includes(day)) {
   // do something
}
因此,在检查数组中的值时,使用includes方法将会非常的方便。
结语
从ES6开始,JavaScript中发生许多变更。对于JavaScript,Angular,React或Vue开发人员都应该知道它们
了解这些变更可以使你成为更棒的开发者,甚至可以帮助您获得更高的薪水。而且,如果你只是在学习React之类的库以及Angular和Vue之类的框架,那么您一定要掌握这些新特性。

版权声明
本文为[葡萄城技术团队]所创,转载请带上原文链接,感谢
https://my.oschina.net/powertoolsteam/blog/4840290

Scroll to Top