es6

1.let、cont和block作用域

  let允许创建块级作用域,ES6推荐在函数中使用let定义变量,而非var。const声明一个常量,同样在块级作用域有效,const声明的变量类似于指针,指向某个引用,也就是说这个【变量】并非一成不变。

var a = 2;
{
  let a =3;
  console.log(a);//3
}
console.log(a);//2
{
  const ARR = [5,6]
  ARR.push(7);
  console.log(ARR);//[5,6,7]
  ARR = 10;//TypeError
}

特征:

  • let关键词声明的变量不具备提升特性
  • let和const声明只在最靠近的一个块中(花括号)有效
  • 当使用常量const声明时,请使用大写变量,如CAPITAL
  • const在声明时必须被赋值,const声明一个只读的常量,一旦声明,常量的值就不能改变。

块级作用域?

  ES5只有全局作用域和函数作用域,没有块级作用域。ES5规定,函数只能在顶层作用域和函数作用域之中生命,不能再跨级作用域声明。

  ES6的块级作用域,允许任何作用域的嵌套。ES6引入了块级作用域,明确允许在块级作用域之中声明函数。ES6允许在跨级作用域内声明函数,函数声明类似于var,即会提升到全局作用域或函数作用域的头部,同时,函数声明还会提升到所在的块级作用域的头部

2.箭头函数

  ES6中,箭头函数就是函数一种简写形式,使用括号包裹参数,跟随一个 =>,紧接着是函数体

var getData = function(){
  return 4.55
}
var getData = () => 4.55

需要注意是是,上面的getData箭头函数采用了简洁函数体,它不需要return语句,下面的李子使用正常函数体:

let arr = ['apple','banana','orange']

let breakfast = arr.map(fruit => {
  return fruit + 's';
})

console.log(breakfast);//["apples", "bananas", "oranges"]

当然,箭头函数不仅仅是让代码变得简洁,函数中this总是绑定总是指向对象本身,具体看下面几个例子。

function Person(){
  this.age = 0;
  setInterval(function growUp(){//在非严格模式下,growUp()函数的this指向window对象
    this.age++;
  },1000);
}
var person = new Person();

我们经常需要使用一个变量来保存this,然后在growUp函数中引用

function Person(){
  var self = this;
  self.age =0;
  setInterval(function growUp(){
    self.age++;
  },1000);
}

然而使用箭头函数可以省却这个麻烦

function Persion(){
  this.age = 0;
  setInterval(() => { //this => person对象
    this.age++;
  },1000);
}

3.函数参数默认值

  ES6运行你对函数参数设置默认值

let getFinalPrice = (price,tax=0.7) => price+price*tax;
getFinalPrice(500);//850

4.Spread/Rest操作符

  Spread、Rest操作符... 需要看上下文语境。

当被用于迭代器中时,它是一个Spread操作符

function foo(x,y,z){
  console.log(x,y,z)
}
let arr = [1,2,3]
foo(...arr);//1 2 3

当被用于函数传参时,是一个Rest操作符

function foo(...args){
  console.log(args);
}
foo(1,2,3,4,5);//[1,2,3,4,5]

5.对象词法扩展

  ES6允许声明在对象字面量时使用简写语法,来初始化属性变量和函数的定义方法,并且允许在对象属性中进行计算操作:

function getCar(make, model, value) {
  return {
    // 简写变量
    make,  // 等同于 make: make
    model, // 等同于 model: model
    value, // 等同于 value: value
 
    // 属性可以使用表达式计算值
    ['make' + make]: true,
 
    // 忽略 `function` 关键词简写对象函数
    depreciate() {
      this.value -= 2500;
    }
  };
}
 
let car = getCar('Barret', 'Lee', 40000);
 
// output: {
//     make: 'Barret',
//     model:'Lee',
//     value: 40000,
//     makeKia: true,
//     depreciate: function()
// }

6.二进制和八进制字面量

 ES6 支持二进制和八进制的字面量,通过在数字前面添加 0o 或者0O 即可将其转换为八进制值:

let oValue = 0o10;
console.log(oValue); // 8
 
let bValue = 0b10; // 二进制使用 `0b` 或者 `0B`
console.log(bValue); // 2

7.对象和数组解构

  解构可以避免在对象赋值时产生中间变量;

function foo(){
  return [1,2,3]
}
let arr = foo();//[1,2,3]

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

function bar(){
  retun {
    x:4,
    y:5,
    z:6
  }
}
let {x:x,y:y,z:z} = bar ();
console.log(x,y,z);//4 5 6

8.对象超类

  ES6允许在对象中使用super方法:

var parent = {
  foo(){
    console.log('Hello from the Parent');
  }
}

var child = {
  foo(){
    super.foo();
    console.log('hello from the child')
  }
}

Object.setPrototypeOf(child,parent);
child.foo();//hello from the parent; 
            //hello from the child

9.模板语法和分隔符

ES6中有一种十分简洁的方法组装一堆字符串和变量

 

  • ${...}用来渲染一个变量
  • ` 作为分隔符
let user  = 'make';
console.log(`Hi $(user}!`); //Hi make

10.for ... of VS for ... in 

for...of 用于遍历一个迭代器,如数组:

let nicknames = ['di','boo','punkey'];
nicknames.size =3;
for (let nickname of nicknames){
  console.log(nickname); //di, boo ,punkey
} 

for... in 用来遍历对象中的属性:

let nicknames = ['di','boo','punkey']
nickname.size = 3;
for(let nickname in nicknames){
  console.log(nickname); //0,1,2,size
}

 

11.Map和WeakMap

  ES6中两种新的数据结构集:Map和WeakMap。事实上每个对象可以看做一个Map.

一个对象由多个key-val对构成,在Map中,任何类型都可以作为对象的key,如:

var myMap = new Map();
 
var keyString = "a string",
    keyObj = {},
    keyFunc = function () {};
 
// 设置值
myMap.set(keyString, "value 与 'a string' 关联");
myMap.set(keyObj, "value 与 keyObj 关联");
myMap.set(keyFunc, "value 与 keyFunc 关联");
 
myMap.size; // 3
 
// 获取值
myMap.get(keyString);    // "value 与 'a string' 关联"
myMap.get(keyObj);       // "value 与 keyObj 关联"
myMap.get(keyFunc);      // "value 与 keyFunc 关联"

WeakMap 就是一个 Map,只不过它的所有 key 都是弱引用,意思就是 WeakMap 中的东西垃圾回收时不考虑,使用它不用担心内存泄漏问题。

另一个需要注意的点是,WeakMap 的所有 key 必须是对象。它只有四个方法 delete(key),has(key),get(key) 和set(key, val):

let w = new WeakMap();
w.set('a', 'b'); 
// Uncaught TypeError: Invalid value used as weak map key
 
var o1 = {},
    o2 = function(){},
    o3 = window;
 
w.set(o1, 37);
w.set(o2, "azerty");
w.set(o3, undefined);
 
w.get(o3); // undefined, because that is the set value
 
w.has(o1); // true
w.delete(o1);
w.has(o1); // false

12.Set和WeakSet

  set对象是一组不重复的值,重复的值将被忽略,值类型可以是原始类型和引用类型:

let mySet = new Set([1,1,2,2,3,3]);
mySet.size = 3;//3
mySet.has(1);//true
mySet.add('string');
mySet.add([a:1,b:2});

可以通过forEach和for...of来遍历Set对象:

mySet.forEach((item) => {
  console.log(item);
    // 1
    // 2
    // 3
    // 'strings'
    // Object { a: 1, b: 2 }
});
 
for (let value of mySet) {
  console.log(value);
    // 1
    // 2
    // 3
    // 'strings'
    // Object { a: 1, b: 2 }
}

Set同样有delete()和clear()方法。

WeakSet

  类似于WeakSet,WeakSet对象可以让你在一个集合中保存对象的弱引用,在WeakSet中的对象允许出现一次:

var ws = new WeakSet();
var obj = {};
var foo = {};

ws.add(window);
ws.add(obj);

ws.has(window);//true
ws.has(foo); //fase,foo没有添加成功

ws.delete(window);//从结合中删除window对象
ws.has(window); //false,window对象已经被删除

13.类

  ES6中有class语法,值得注意的是,这里的class不是新的对象继承模型,它只是原型链的语法糖表现形式。函数中使用static关键词定义构造函数的方法和属性:

class Task(){
  constructor(){
    console.log('task instantiated!');
  }
 
  showId(){
    console.log(23)
  }

  static loadAll(){
    console.log('Loading all tasks..');
  }
}

console.log(typeof Task); //function
let task = new Task(); // 'task instantiated'
task.showId(); //23
Task.loadAll(); // loading all task..

类中的继承和超集

class Car(){
  constructor(){
    console.log('Creating a new car')
  }
}

class Porsche extends Car{
  constructor(){
    super();
    console.log('creating Porsche')
  }
}

let c = new Porsche();// creating a new car; creating Porsche

extends允许一个子类继续父类,需要注意的是,子类的constructor函数中需要执行super()函数。

当然,你也可以在子类方法中调用方法,如super.parentMethodName().

注意几点:

 

  • 类的声明不会提升,如果你要使用某个class,那你必须在使用之前定义它,否则会抛出一个ReferenceError的错误
  • 在类中定义函数不需要使用function关键词

14.Symbol

  symbol是一种新的数据类型,它的值是唯一的,不可变的。ES中提出symbol的目的是为了生成一个唯一的标识符,不过你访问不到这个标识符:

var sym = Symbol('some optional description');
console.log(typeof sym);//symbol

注意,这里symbol前面不能使用new操作符。

如果它被用作一个对象的属性,那么这个属性会是不可枚举的:

var o = {
  val:10,
  [Symbol('random')]:'i am a symbol',
}

console.log(Object.getOwnPropertyNames(o); //val

如果要获取对象 symbol 属性,需要使用Object.getOwnPropertySymbols(o)。

15.迭代器(Iterators)

  迭代器允许每次访问数据集合的一个元素,当指针指向数据集合最后一个元素是,迭代器便会退出,它提供了next()来遍历一个序列,这个方法返回一个包含done和value属性的对象。

  ES6中可以通过Symbol.iterator给对象设置默认的遍历器,无论什么时候对象需要被遍历,执行它的@@iterator方法便可以返回一个用于获取值的迭代器。

数组默认就是一个迭代器:

var arr = [11,12,13];
var itr = arr[Symbol.iterator]();
 
itr.next(); // { value: 11, done: false }
itr.next(); // { value: 12, done: false }
itr.next(); // { value: 13, done: false }
 
itr.next(); // { value: undefined, done: true }

16.Generators

  Generators函数是ES6的新特性,它允许一个函数的可遍历对象生成多个值,在使用中你会看到*语法和一个新的关键词yield

function *infiniteNumbers() {
  var n = 1;
  while (true){
    yield n++;
  }
}
 
var numbers = infiniteNumbers(); // returns an iterable object
 
numbers.next(); // { value: 1, done: false }
numbers.next(); // { value: 2, done: false }
numbers.next(); // { value: 3, done: false }

  每次执行yield时,返回的值变为迭代器的下一个值。

17.Promise

  ES6对Promise有原生的支持,一个Promise是一个等待被异步执行的对象,当它被执行完成后,其状态会变成ressolved或者rejected。

var p = new Promise(function(resolve, reject) {  
  if (/* condition */) {
    // fulfilled successfully
    resolve(/* value */);  
  } else {
    // error, rejected
    reject(/* reason */);  
  }
});

每一个Promise都有一个.then方法,这个方法接受两个参数,第一个是处理resolved状态的回调,一个是处理rejected状态的回调:

p.then((val) => console.log("Promise Resolved", val),
       (err) => console.log("Promise Rejected", err));

18.变量的解构赋值

  解构赋值的规则是,只要等号右边的值不是对象或数组,就先将其转为对象。由于undefined和null无法转为对象,所以对他们进行解构赋值都会报错。undefined会触发变量的参数的默认值。

不能使用圆括号

  1)变量声明语句;

// 全部报错
let [(a)] = [1];

let {x: (c)} = {};
let ({x: c}) = {};
let {(x: c)} = {};
let {(x): c} = {};

let { o: ({ p: p }) } = { o: { p: 2 } };

  2)函数参数。函数参数也属于变量声明,因此不能带有圆括号。

// 报错
function f([(z)]) { return z; }
// 报错
function f([z,(x)]) { return x; }

  3)赋值语句的模式。

// 全部报错
({ p: a }) = { p: 42 };
([a]) = [5];

可以使用圆括号

  1)赋值语句的非模式部分,可以使用圆括号。

[(b)] = [3]; // 正确
({ p: (d) } = {}); // 正确
[(parseInt.prop)] = [3]; // 正确

  用途

    1)变换变量的值

let x = 1;
let y = 2;

[x, y] = [y, x]

  2)从函数返回多个值

//返回一个数组

function example(){
  return [1, 2, 3]
}

let [a, b, c] = example();

//返回一个对象
function example(){
  return {
    foo: 1,
    bar: 2
  }
}

let {foo, bar} = example();

3)函数参数的定义

  解构赋值可以方便地讲一组参数与变量名对应起来

//参数是一组有次序的值
function f([x, y, z]){ ... }

f([1, 2, 3])

//参数是一组无次序的值
function f({x, y, z}){ ... }
f({z:3, y:2, x:1})

4)提取JSON数据

let jsonData = {
  id: 42,
  status: "OK",
  data:[867, 100]
}

let  {id, status, data} = jsonData;
console.log(id, status, data)
//42, ok, [867, 100]

5)函数参数的默认值

jQuery.ajax = function(url, {
  async = true,
  beforeSend = function(){},
  cache = true,
  complete = function(){},
  crossDomain = false,
  global = true,
} = {}) {
  // ... do stuff
};

6)遍历Map解构

const map = new Map();
map.set('first', 'hello')
map.set('second', 'world')

for (let [key, value] of map) {
  console.log(key+'is'+value);
}

//first is hello;
//second is world;

7)输入模块的指定方法

const { SourceMapConsumer, SourceNode } = require('source-map');

 

你可能感兴趣的:(ES6)