Sanakey

ES6常用新特性(一)
前言ES6增加了不少新特性,下面总结了一下比较常用的新特性。let const解构赋值模板字符串数组拓展箭头函数对象拓展
扫描右侧二维码阅读全文
20
2018/03

ES6常用新特性(一)

前言

ES6增加了不少新特性,下面总结了一下比较常用的新特性。

  • let const
  • 解构赋值
  • 模板字符串
  • 数组拓展
  • 箭头函数
  • 对象拓展

let

function test(){
  for(let i=1;i<3;i++){
    console.log(i);// 1  2
  }
  console.log(i); // Uncaught ReferenceError: i is not defined
//如果是var则此处i=3

    let a = 1;
    let a = 2;
    //报错Uncaught SyntaxError: Identifier 'a' has already been declared

}
test();
  • let拥有块级作用域(花括号内就是一个块)
  • let不存在变量提升
  • es6强制开启严格模式
    严格模式下,没有变量提升,变量未声明,不能引用,报错Uncaught ReferenceError: a is not defined,而不是undefined
  • let声明后的变量不能重复声明

const

function last(){
   const PI=3.14159265;
   PI = 6;
   console.log(PI); //Uncaught TypeError: Assignment to constant variable.
   
   
   const PI;
   PI = 6;
   console.log(PI);//Uncaught SyntaxError: Missing initializer in const declaration
   
   
   const x={
     a:1
   }
   console.log(x); //{a: 1}
   
   //x.b=2;
   //console.log(x); //{a: 1, b: 2}
 
 }
 last();
  • const同样拥有块级作用域
  • const声明基础类型值时是常量,不能被赋值修改
  • const必须声明时赋值,否则报错Uncaught SyntaxError: Missing initializer in const declaration
  • const声明引用类型值时,可以被修改

解构赋值

  • 什么是解构赋值?
    ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构

数组解构赋值

let [a, b, c] = [1, 2, 3];

//等价于
let a = 1;
let b = 2;
let c = 3;

let [a, b, c=3] = [1, 2]; 
console.log(a,b,c); //1,2,3

let [a, b, c] = [1, 2]; 
console.log(a,b,c); //1,2,undefined


{
  let a,b,c;
  [a,b,...c]=[1,2,3,4,5,6];
  console.log(a,b,c);
  //1,2,[3, 4, 5, 6]
}

适用场景

//变量交换
{
  let a=1;
  let b=2;
  [a,b]=[b,a];
  console.log(a,b);  //2,1
}

//数组
{
  function fn(){
    return [1,2]
  }
  let a,b;
  [a,b]=fn();
  console.log(a,b);  //1,2
  //es5需要用数组下标获取对应值
  //a = fn()[0];
  //b = fn()[1];
}

//返回多个值时,可以选择性的接受某几个变量
{
  function fn(){
    return [1,2,3,4,5]
  }
  let a,b,c;
  [a,,,b]=fn();
  console.log(a,b);  //1,4
}

//不确定数组返回长度时,想要的值只有前几个
{
  function fn(){
    return [1,2,3,4,5]
  }
  let a,b,c;
  [a,,...b]=fn();
  console.log(a,b);  //1,[3, 4, 5]
}
  //let a,b,c;
  //[a,,...b,c]=fn();
  //console.log(a,b,c);
  //Uncaught SyntaxError: Rest element must be last element
  //...b必须是最后一个元素

对象解构赋值

{
  let a,b;
  ({a,b}={a:1,b:2})
  console.log(a,b); //1,2
}

{
  let a={x:42,y:true};
  let {x,y}=a;
  console.log(x,y); //42,true
}

{
  let {a=10,b=5}={a:3};
  console.log(a,b); //3,5
}

适用场景

//获取对象的属性值
{
  let metaData={
    title:'abc',
    test:[{
      title:'test',
      desc:'description'
    }]
  }
  let {title:esTitle,test:[{title:cnTitle}]}=metaData;
  console.log(esTitle,cnTitle);  
  //abc,test
}

字符串的拓展

includes(), startsWith(), endsWith()

  • includes():返回布尔值,表示是否找到了参数字符串。
  • startsWith():返回布尔值,表示参数字符串是否在原字符串的头部。
  • endsWith():返回布尔值,表示参数字符串是否在原字符串的尾部。
let s = 'Hello world!';

s.startsWith('world', 6) // true
s.endsWith('Hello', 5) // true
s.includes('Hello', 6) // false

repeat()

repeat方法返回一个新字符串,表示将原字符串重复n次。

'x'.repeat(3) // "xxx"
'hello'.repeat(2) // "hellohello"
'na'.repeat(0) // ""

模板字符串

模板字符串(template string)是增强版的字符串,用反引号(`)标识。它可以当作普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量。

{
  let name="list";
  let info="hello world";
  let m=`i am ${name},${info}`;
  console.log(m);  //i am hello, world
}
  • 使用模板字符串表示多行字符串,所有的空格和缩进都会被保留在输出之中。

padStart(),padEnd()

ES2017引入了字符串补全长度的功能。

  • padStart()用于头部补全
  • padEnd()用于尾部补全。
{
//日期补全,个位数补全等等
  console.log('1'.padStart(2,'0'));
  console.log('1'.padEnd(2,'0'));
}

数值拓展

Number.isInteger()

Number.isInteger()用来判断一个数值是否为整数。

Number.isInteger(25) // true
Number.isInteger(25.0) // true
Number.isInteger(25.1) // false
  • 如果参数不是数值,Number.isInteger返回false

数组的拓展

扩展运算符

扩展运算符可以展开数组

//替代函数的apply方法
// ES5 的写法
Math.max.apply(null, [14, 3, 77])

// ES6 的写法
Math.max(...[14, 3, 77])

// 等同于
Math.max(14, 3, 77);

适用场景

  • 复制数组
//es5写法
const a1 = [1, 2];
const a2 = a1.concat();

a2[0] = 2;
a1 // [1, 2]

//es6写法
const a1 = [1, 2];
// 写法一
const a2 = [...a1];
// 写法二
const [...a2] = a1;
  • 合并数组
    注意:这两种方法都是浅拷贝
const arr1 = ['a', 'b'];
const arr2 = ['c'];
const arr3 = ['d', 'e'];

// ES5 的合并数组
arr1.concat(arr2, arr3);
// [ 'a', 'b', 'c', 'd', 'e' ]

// ES6 的合并数组
[...arr1, ...arr2, ...arr3]
// [ 'a', 'b', 'c', 'd', 'e' ]
  • 与解构赋值结合
    与解构赋值结合起来,用于生成数组。
// ES5
a = list[0], rest = list.slice(1)
// ES6
[a, ...rest] = list
  • 字符串
    将字符串转为真正的数组。
[...'hello']
// [ "h", "e", "l", "l", "o" ]

Array.of

Array.of方法用于将一组值,转换为数组。

{
  let arr = Array.of(3,4,5,6,7);
  console.log('arr=',arr); //arr=[3,4,5,6,7]

  let empty=Array.of();
  console.log('empty',empty); //empty=[]
}

Array.from

Array.from方法用于将两类对象转为真正的数组:类似数组的对象(array-like
object)和可遍历(iterable)的对象(包括 ES6 新增的数据结构 Set 和 Map)。

{
  let p=document.querySelectorAll('p');
  let pArr=Array.from(p);
  pArr.forEach(function(item){
    console.log(item.textContent);
  });

//Array.from还可以接受第二个参数,作用类似于数组的map方法,用来对每个元素进行处理,将处理后的值放入返回的数组。
  console.log(Array.from([1,3,5],function(item){return item*2})); //[2,6,10]
}

entries(),keys() 和 values()

  • keys()是对键名的遍历
  • values()是对键值的遍历
  • entries()是对键值对的遍历。
{
  for(let index of ['1','a','bc'].keys()){
    console.log('keys',index);  //0 1 2
  }
  for(let value of ['1','a','bc'].values()){
    console.log('values',value);  //1 a ac
  }
  for(let [index,value] of ['1','a','bc'].entries()){
    console.log('entries',index,value); //0 1, 1 a, 2 bc
  }
}

find() findIndex() 和includes()

  • find()找出第一个符合条件的数组成员
  • findIndex()返回第一个符合条件的数组成员的位置
  • includes()返回一个布尔值,表示某个数组是否包含给定的值
{
  console.log([1,2,3,4,5,6].find(function(item){return item>3}));
  //4
  console.log([1,2,3,4,5,6].findIndex(function(item){return item>3}));
  //3
  
  console.log('number',[1,2,NaN].includes(1)); //true
  console.log('number',[1,2,NaN].includes(NaN));  //true
}

函数的拓展

默认值

{
//es5写法
    function log(x, y) {
      y = y || 'World';
      console.log(x, y);
    }

//es6写法
  function test(x, y = 'world'){
    console.log('默认值',x,y);
  }
  test('hello');  //默认值 hello world
  test('hello','kill');  //默认值 hello kill
}

//作用域
//es6写法
{
  let x='test';
  function test2(x,y=x){
    console.log('作用域',x,y);
  }
  test2('kill');
}
//等价于
//es5写法
{
  var x='test';
  function test2(x,y){
    y = x;
    console.log('作用域',x,y);
  }
  test2('kill');
}

rest参数

rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。

{
  function test3(...arg){
    for(let v of arg){
      console.log('rest',v);
    }
  }
  test3(1,2,3,4,'a');
    //rest 1
    //rest 2
    //rest 3
    //rest 4
    //rest a
}

{
  console.log(...[1,2,4]);  //1 2 4
  console.log('a',...[1,2,4]); //a 1 2 4
}

rest 参数之后不能再有其他参数(即只能是最后一个参数),否则会报错。

箭头函数

箭头函数有几个使用注意点。

  • 函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。
  • 不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。
  • 不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。
var f = v => v;
// 等同于
var f = function (v) {
  return v;
};


//不需要参数时,可以用圆括号代替参数部分
var f = () => 5;
// 等同于
var f = function () { return 5 };

var sum = (num1, num2) => num1 + num2;
// 等同于
var sum = function(num1, num2) {
  return num1 + num2;
};


{
  let arrow = v => v*2;
  let arrow2 = () => 5;
  console.log('arrow',arrow(3  //arrow 6
  console.log(arrow2());  //5

}

简化回调函数

// 正常函数写法
[1,2,3].map(function (x) {
  return x * x;
});

// 箭头函数写法
[1,2,3].map(x => x * x);

改变this指向

// ES6
function foo() {
  setTimeout(() => {
    console.log('id:', this.id);
  }, 100);
}

// ES5
function foo() {
  var _this = this;

  setTimeout(function () {
    console.log('id:', _this.id);
  }, 100);
}

尾调用

某个函数的最后一步是调用另一个函数,就是尾调用

function f(x){
  return g(x);
} 

尾调用的好处:尾调用优化

  • 尾调用优化,就是使用尾递归,对于尾递归来说,由于只存在一个调用帧,所以永远不会发生“栈溢出”错误。
  • ES6规定,所有 ECMAScript 的实现,都必须部署“尾调用优化”。
{
  function tail(x){
    console.log('tail',x);
  }
  function fx(x){
    return tail(x)
  }
  fx(123)
}

对象的拓展

简洁表示法

{
  // 简洁表示法
  let o=1;
  let k=2;
  let es5={
    o:o,
    k:k
  };
  let es6={
    o,
    k
  };
  console.log(es5,es6);

  let es5_method={
    hello:function(){
      console.log('hello');
    }
  };
  let es6_method={
    hello(){
      console.log('hello');
    }
  };
  console.log(es5_method.hello(),es6_method.hello());
}

属性表达式

{
  // 属性表达式
  let a='x';
  let es5_obj={
    a:'c',
    b:'c'
  };

  let es6_obj={
    [a]:'c'
  }
  console.log(es5_obj,es6_obj);
  //{a: "c", b: "c"} {x: "c"}

}

注意,属性名表达式与简洁表示法,不能同时使用,会报错。

// 报错
const foo = 'bar';
const bar = 'abc';
const baz = { [foo] };

// 正确
const foo = 'bar';
const baz = { [foo]: 'abc'};

Object.is(),Object.assign()

  • Object.is()用来比较两个值是否严格相等,与严格比较运算符(===)的行为基本一致。
  • Object.assign()可以实现对象的浅拷贝
{
  // 新增API
  console.log('字符串',Object.is('abc','abc'),'abc'==='abc');  //true true
  console.log('数组',Object.is([],[]),[]===[]); //数组 false false

  console.log('拷贝',Object.assign({a:'a'},{b:'b'})); //拷贝 {a: "a", b: "b"}

  let test={k:123,o:456};
  for(let [key,value] of Object.entries(test)){
    console.log([key,value]);  //["k", 123] ["o", 456]
  }
}
{
  // 扩展运算符
   let {a,b,...c}={a:'test',b:'kill',c:'ddd',d:'ccc'};
   c={
     c:'ddd',
     d:'ccc'
   }
}

参考

阮一峰 ECMAScript 6 入门

Last modification:November 3rd, 2019 at 03:54 pm
如果觉得我的文章对你有用,请随意赞赏

Leave a Comment

reimu.png