ES6基础

Posted 木头南方

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ES6基础相关的知识,希望对你有一定的参考价值。

最近在做微信小程序  才有机会了解到ES6,之前从没javascript,以为前台都有框架,偶尔的操作就是利用jquery进行ajax请求,声明标量就是var啦,

一切都是普普通通的进行中,真没注意到js还有什么标准,知道要做微信小程序了。

首先解释下ES是什么?javascript语言的标准,6当然是版本号了。现在标准应该到ES8了。忽然感觉自己好无知啊。

总结下在做微信小程序遇到的ES6的语法知识,简单汇总下别人的劳动成果。

1.Default Parameters(默认参数) in ES6

还记得我们以前不得不通过下面方式来定义默认参数:

var link = function (height, color, url) {
    var height = height || 50;
    var color = color || \'red\';
    var url = url || \'http://azat.co\';
    ...
}

 一切工作都是正常的,直到参数值是0后,就有问题了,因为在JavaScript中,0表示fasly,它是默认被hard-coded的值,而不 能变成参数本身的值。当然,如果你非要用0作为值,我们可以忽略这一缺陷并且使用逻辑OR就行了!但在ES6,我们可以直接把默认值放在函数申明里:

var link = function(height = 50, color = \'red\', url = \'http://azat.co\') {
  ...
}

 顺便说一句,这个语法类似于Ruby!

2.Template Literals(模板对象) in ES6

在其它语言中,使用模板和插入值是在字符串里面输出变量的一种方式。因此,在ES5,我们可以这样组合一个字符串:

var name = \'Your name is \' + first + \' \' + last + \'.\';
var url = \'http://localhost:3000/api/messages/\' + id;

 幸运的是,在ES6中,我们可以使用新的语法$ {NAME},并把它放在反引号里:

var name = `Your name is ${first} ${last}. `;
var url = `http://localhost:3000/api/messages/${id}`;

3.Multi-line Strings (多行字符串)in ES6

ES6的多行字符串是一个非常实用的功能。在ES5中,我们不得不使用以下方法来表示多行字符串:
var roadPoem = \'Then took the other, as just as fair,nt\'
    + \'And having perhaps the better claimnt\'
    + \'Because it was grassy and wanted wear,nt\'
    + \'Though as for that the passing therent\'
    + \'Had worn them really about the same,nt\';
var fourAgreements = \'You have the right to be you.n
    You can only be you when you do your best.\';

 然而在ES6中,仅仅用反引号就可以解决了:

var roadPoem = `Then took the other, as just as fair,
    And having perhaps the better claim
    Because it was grassy and wanted wear,
    Though as for that the passing there
    Had worn them really about the same,`;
var fourAgreements = `You have the right to be you.
    You can only be you when you do your best.`;

 

4.Destructuring Assignment (解构赋值)in ES6

解构可能是一个比较难以掌握的概念。先从一个简单的赋值讲起,其中house 和 mouse是key,同时house 和mouse也是一个变量,在ES5中是这样:

var data = $(\'body\').data(), // data has properties house and mouse
   house = data.house,
   mouse = data.mouse;

 在ES6,我们可以使用这些语句代替上面的ES5代码:

var { house, mouse} = $(\'body\').data(); // we\'ll get house and mouse variables
var {jsonMiddleware} = require(\'body-parser\');
var {username, password} = req.body;

 这个同样也适用于数组,非常赞的用法:

var [col1, col2]  = $(\'.column\'),
   [line1, line2, line3, , line5] = file.split(\'n\');

 我们可能需要一些时间来习惯解构赋值语法的使用,但是它确实能给我们带来许多意外的收获

 

4.对象字面量 与 class

ES6针对对象字面量做了许多简化语法的处理。

当属性与值的变量同名时。

const name = \'Jane\';
const age = 20

// es6
const person = {
  name,
  age
}

// es5
var person = {
  name: name,
  age: age
};

 那么这种方式在任何地方都可以使用,比如在一个模块对外提供接口时

const getName = () => person.name;
const getAge = () => person.age;

// commonJS的方式
module.exports = { getName, getAge }

// ES6 modules的方式
export default { getName, getAge  }

 除了属性之外,对象字面量写法中的方法也可以有简写方式

// es6
const person = {
  name,
  age,
  getName() { // 只要不使用箭头函数,this就还是我们熟悉的this
    return this.name
  }
}

// es5
var person = {
  name: name,
  age: age,
  getName: function getName() {
    return this.name;
  }
};

 在对象字面量中可以使用中括号作为属性,表示属性也能是一个变量了。

const name = \'Jane\';
const age = 20

const person = {
  [name]: true,
  [age]: true
}

 在ant-design的源码实现中,就大量使用了这种方式来拼接当前元素的className,例如:

let alertCls = classNames(prefixCls, {
      [`${prefixCls}-${type}`]: true,
      [`${prefixCls}-close`]: !this.state.closing,
      [`${prefixCls}-with-description`]: !!description,
      [`${prefixCls}-no-icon`]: !showIcon,
      [`${prefixCls}-banner`]: !!banner,
 }, className)

 class

ES6为我们创建对象提供了新的语法糖,这就是Class语法。如果你对ES5中面向对象的方式比较熟悉的话,Class掌握起来也是非常迅速的,因为除了写法的不同,它并不会增加新的难以理解的知识点。我们先利用一个简单的例子来看看写法的不同。

// ES5
// 构造函数
function Person(name, age) {
  this.name = name;
  this.age = age;
}

// 原型方法
Person.prototype.getName = function() {
  return this.name
}

// ES6
class Person {
  constructor(name, age) {  // 构造函数
    this.name = name;
    this.age = age;
  }

  getName() {  // 原型方法
    return this.name
  }
}

 除此之外,我们还需要特别注意在实际使用中的几种写法方式的不同,在下面的例子注释中,我说明了他们分别对应的ES5中的含义

class Person {
  constructor(name, age) {  // 构造函数
    this.name = name;
    this.age = age;
  }

  getName() {   // 这种写法表示将方法添加到原型中
    return this.name
  }

  static a = 20;  // 等同于 Person.a = 20

  c = 20;   // 表示在构造函数中添加属性 在构造函数中等同于 this.c = 20

// 箭头函数的写法表示在构造函数中添加方法,在构造函数中等同于this.getAge = function() {}
  getAge = () => this.age   

}

 箭头函数需要注意的仍然是this的指向问题,因为箭头函数this指向不能被改变的特性,因此在react组件中常常利用这个特性来在不同的组件进行传值会更加方便。

继承 extends

相比ES5,ES6的继承就要简单很多,我们直接来看一个例子。
class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }

  getName() {
    return this.name
  }
}

// Student类继承Person类
class Student extends Person {
  constructor(name, age, gender, classes) {
    super(name, age);
    this.gender = gender;
    this.classes = classes;
  }

  getGender() {
    return this.gender;
  }
}

 

我们只需要一个extends关键字,就可以实现继承了,不用像ES5那样去担心构造函数继承和原型继承,除此之外,我们还需要关注一个叫做super的方法。

在继承的构造函数中,我们必须如上面的例子那么调用一次super方法,它表示构造函数的继承,与ES5中利用call/apply继承构造函数是一样的功能

// 构造函数中
// es6 
super(name, age);

// es5
Person.call(this);

    super还可以直接调用父级的原型方法,super.getName,但是我自己从来没这样用过,也就不扩展说了。

继承在react中有大量的使用场景,许多组件都利用继承来创建。

import React, { Component } from \'react\';

class App extends Component {

  defaultProps = {}
  state = {}
  componentWillMount() {}
  componentDidMount() {}

  btnClick = e => {}

  render() {}
}

 

5.Block-Scoped Constructs Let and Const(块作用域和构造let和const)

在ES6代码中,你可能已经看到那熟悉的身影let。在ES6里let并不是一个花俏的特性,它是更复杂的。Let是一种新的变量申明方式,它允许你把变量作用域控制在块级里面。我们用大括号定义代码块,在ES5中,块级作用域起不了任何作用:

function calculateTotalAmount (vip) {
  var amount = 0;
  if (vip) {
    var amount = 1;
  }
  { // more crazy blocks!
    var amount = 100;
    {
      var amount = 1000;
    }
  }  
  return amount;
}
console.log(calculateTotalAmount(true));

 结果将返回1000,这真是一个bug。在ES6中,我们用let限制块级作用域。而var是限制函数作用域。

function calculateTotalAmount (vip) {
  var amount = 0; // probably should also be let, but you can mix var and let
  if (vip) {
    let amount = 1; // first amount is still 0
  } 
  { // more crazy blocks!
    let amount = 100; // first amount is still 0
    {
      let amount = 1000; // first amount is still 0
    }
  }  
  return amount;
}
 
console.log(calculateTotalAmount(true));

 这个结果将会是0,因为块作用域中有了let。如果(amount=1).那么这个表达式将返回1。谈到const,就更加容易了;它就是一个不变量,也是块级作用域就像let一样。下面是一个演示,这里有一堆常量,它们互不影响,因为它们属于不同的块级作用域:

function calculateTotalAmount (vip) {
  const amount = 0;  
  if (vip) {
    const amount = 1;
  } 
  { // more crazy blocks!
    const amount = 100 ;
    {
      const amount = 1000;
    }
  }  
  return amount;
}
console.log(calculateTotalAmount(true));

 

6.Modules (模块)in ES6

众所周知,在ES6以前JavaScript并不支持本地的模块。人们想出了AMD,RequireJS,CommonJS以及其它解决方法。现在ES6中可以用模块import 和export 操作了。

在ES5中,你可以在<script>中直接写可以运行的代码(简称IIFE),或者一些库像AMD。然而在ES6中,你可以用export导入你的类。下面举个例子,在ES5中,module.js有port变量和getAccounts 方法:

module.exports = {  port: 3000,  getAccounts: function() {    ...  }}

 在ES5中,main.js需要依赖require(‘module’) 导入module.js:

var service = require(\'module.js\');console.log(service.port); // 3000

 但在ES6中,我们将用export and import。例如,这是我们用ES6 写的module.js文件库:

export var port = 3000;export function getAccounts(url) {  ...}

 如果用ES6来导入到文件main.js中,我们需用import {name} from ‘my-module’语法,例如:

import {port, getAccounts} from \'module\';console.log(port); // 3000

 或者我们可以在main.js中把整个模块导入, 并命名为 service:

import * as service from \'module\';console.log(service.port); // 3000

 

7.Arrow Functions in(箭头函数) ES6

之前我说ES6颠覆了js的编码习惯,箭头函数的使用占了很大一部分。

首先是写法上的不同:

// es5
var fn = function(a, b) {
    return a + b;
}

// es6 箭头函数写法,当函数直接被return时,可以省略函数体的括号
const fn = (a, b) => a + b;

// es5
var foo = function() {
    var a = 20;
    var b = 30;
    return a + b;
}

// es6
const foo = () => {
   const a = 20;
   const b = 30;
   return a + b;
}

 箭头函数可以替换函数表达式,但是不能替换函数声明

其次还有一个至关重要的一点,那就是箭头函数中,没有this。如果你在箭头函数中使用了this,那么该this一定就是外层的this。

也正是因为箭头函数中没有this,因此我们也就无从谈起用call/apply/bind来改变this指向。记住这个特性,能让你在react组件之间传值时少走无数弯路

var person = {
    name: \'tom\',
    getName: function() {
        return this.name;
    }
}

// 我们试图用ES6的写法来重构上面的对象
const person = {
    name: \'tom\',
    getName: () => this.name
}

// 但是编译结果却是
var person = {
    name: \'tom\',
    getName: function getName() {
        return undefined.name;
    }
};

 

在ES6中,会默认采用严格模式,因此this也不会自动指向window对象了,而箭头函数本身并没有this,因此this就只能是undefined,这一点,在使用的时候,一定要慎重慎重再慎重,不然踩了坑你都不知道自己错在哪!这种情况,如果你还想用this,就不要用使用箭头函数的写法。

// 可以稍做改动
const person = {
    name: \'tom\',
    getName: function() {
        return setTimeout(() => this.name, 1000);
    }
}

// 编译之后变成
var person = {
    name: \'tom\',
    getName: function getName() {
        var _this = this;  // 使用了我们在es5时常用的方式保存this引用

        return setTimeout(function () {
            return _this.name;
        }, 1000);
    }
};

 先记住箭头函数的写法,并留意箭头函数中关于this的特殊性,更过实践与注意事项我们在封装react组件时再慢慢来感受。

 

8.Promise

下一篇文章专门来个promise的讲解  当然也是别人的成功  这里只是坐下记录

 

参考:https://www.oschina.net/news/71566/es6-developers-will-have-to-know

          https://www.cnblogs.com/libin-1/p/6716470.html

 

以上是关于ES6基础的主要内容,如果未能解决你的问题,请参考以下文章

[vscode]--HTML代码片段(基础版,reactvuejquery)

ES6 模块串联

ES6解构赋值

ES7-Es8 js代码片段

ES6基础语法

JavaScript ES6 的let和const