关闭搜索(ESC)
搜索标签:

ES6学习记录

2016-01-18 浏览:890 标签: es6

描述

会记录一些关于ES6,我觉得感兴趣的东西。·

let & const

let: 作用域内有效

var a = [];
for(let i=0; i<20;i++) {
    a[i] = function() {
        console.log(i);
    }
}
a[6](); // 6

es5函数作用域 && es6块级作用域

因为es6的块级作用域,消除了es5的作用域提升。

function f() {
    console.log('I am outside');
}

(function() {
    if(false) {
        function f() {
            console.log('I am inside');
        }
    }
    f();
})();

// es5: I am inside
// es6: I am outside

const: 声明常量不变。(和C用法类似)

跨模块常量

const只在当前有用,如何设置跨模块常量。

// components.js
export const a = 1;
export const b = 2;
export const c = 3;

// test1.js
import * as coms from './components.js';
console.log(coms.a);
console.log(coms.b);
console.log(coms.c);

// test2.js
import {a, b} from './components.js';
console.log(a);

变量的解构复制

function add([x, y]) {
    return x + y;
}

add([1, 2]);

模板字符串

$("#result").append(`
  There are <b>${basket.count}</b> items
   in your basket, <em>${basket.onSale}</em>
  are on sale!
`);

数值的扩展

Math.sign方法判断一个数是正数还是负数还是0;

Math.hypot方法返回所有参数的平方和的平方根;

函数的扩展

name属性

返回该函数的函数名。

function aname() {
    return aname.name;
}

箭头函数定义

eg:

var f = () => 5;
// 等同于
var f = function (){ return 5 };

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

箭头函数的用处

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

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

箭头函数注意点

1:函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象
2:不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。
3:不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用Rest参数代替。
4:不可以使用yield命令,因此箭头不能用作Generator函数。

eg:

const pipeline = (...funcs) =>
  val => funcs.reduce((a, b) => b(a), val);

const plus1 = a => a + 1;
const mult2 = a => a * 2;
const addThenMult = pipeline(plus1, mult2);

addThenMult(5)
// 12

函数绑定

ES7的一个提案,不顾babel转码器已经支持。

函数绑定运算符是并排的两个双冒号(::),双冒号左边是一个对象,右边是一个函数。该运算符会自动将左边的对象,作为上下文环境(this对象),绑定到右边的函数上面。

foo::bar;
// 等同于
bar.bind(foo);

foo::bar(...arguments);
// 等同于
bar.apply(foo, arguments);

const hasOwnProperty = Object.prototype.hasOwnProperty;
function hasOwn(obj, key) {
  return obj::hasOwnProperty(key);
}

对象的简洁用法

函数式对象

var o = {
    method() {
        return 'hello';
    }
};

// 等价于
var o = {
    method: function() {
        return 'hello';
    }
}

eg:

var birth = '2000/01/01';

var Person = {

  name: '张三',

  //等同于birth: birth
  birth,  //这种写法将对象写法就更加简单了

  // 等同于hello: function ()...
  hello() { console.log('我的名字是', this.name); }

};

// example 2
module.exports = { getItem, setItem, clear };
// 等同于
module.exports = {
  getItem: getItem,
  setItem: setItem,
  clear: clear
};

Object.is()

+0 === -0 //true
NaN === NaN // false

Object.is(+0, -0) // false
Object.is(NaN, NaN) // true

Symbol

新引入原始数据类型Symbol

完全独立,与任何值都不相等。

var s1 = Symbol('foo');
var s2 = Symbol('foo');
console.log(s1 == s2); // false

特点:无法被修改。

eg:

var mySymbol = Symbol();

// 第一种写法
var a = {};
a[mySymbol] = 'Hello!';

// 第二种写法
var a = {
  [mySymbol]: 'Hello!'
};

// 第三种写法
var a = {};
Object.defineProperty(a, mySymbol, { value: 'Hello!' });

// 以上写法都得到同样结果
a[mySymbol] // "Hello!"

魔术字符串

含义:没有被赋值给变量的,直接用在各种表达式中的字符串。

魔术字符串与代码具有强耦合,不利于维护。

eg:

function getArea(shape, options) {
  var area = 0;

  switch (shape) {
    case 'Triangle': // 魔术字符串
      area = .5 * options.width * options.height;
      break;
    /* ... more code ... */
  }

  return area;
}

getArea('Triangle', { width: 100, height: 100 }); // 魔术字符串

'Triangle'就是魔术字符串

需要换为:

var shapeType = {
  triangle: 'Triangle'
};

function getArea(shape, options) {
  var area = 0;
  switch (shape) {
    case shapeType.triangle:
      area = .5 * options.width * options.height;
      break;
  }
  return area;
}

getArea(shapeType.triangle, { width: 100, height: 100 });

利用Symbol可以消除shapeType被别人覆盖。

const shapeType = {
    triangle: Symbol()
}

二进制数组

二进制数组与字符串转化

// ArrayBuffer转为字符串,参数为ArrayBuffer对象
function ab2str(buf) {
  return String.fromCharCode.apply(null, new Uint16Array(buf));
}

// 字符串转为ArrayBuffer对象,参数为字符串
function str2ab(str) {
  var buf = new ArrayBuffer(str.length * 2); // 每个字符占用2个字节
  var bufView = new Uint16Array(buf);
  for (var i = 0, strLen = str.length; i < strLen; i++) {
    bufView[i] = str.charCodeAt(i);
  }
  return buf;
}

set && map数据结构

Set数据结构,类似数组,里面的所有值都是唯一的。

eg:

var s = new Set();
[2,3,4,5,6,7,2,3,4,5,6].map(x => s.add(x));
console.log(s); // [2,3,4,5,6,7]

注意:在Set内部,NaN是相等的,但是两个对象永远是不相等的。

WeekSet

与Set类似,只能是对象,不能是其他类型。

map数据结构,就是键值对的集合。

eg:

var m = new Map();

m.set("edition", 6)        // 键是字符串
m.set(262, "standard")     // 键是数值
m.set(undefined, "nah")

m.get('edition'); // 6

Generator

  • && yield

eg:

var arr = [1, [[2, 3], 4], [5, 6]];

var flat = function* (a) {
  a.forEach(function (item) {
    if (typeof item !== 'number') {
      yield* flat(item);
    } else {
      yield item;
    }
  }
};

for (var f of flat(arr)){
  console.log(f);
}

实现状态机:

var clock = function*(_) {
  while (true) {
    yield _;
    console.log('Tick!');
    yield _;
    console.log('Tock!');
  }
};
var a = clock('1');
a.next(); // 1
a.next(); // Tick!
a.next(); // Tock!

异步同步化:

function* loadUI() {
  showLoadingScreen();
  yield loadUIDataAsynchronously();
  hideLoadingScreen();
}
var loader = loadUI();
// 加载UI
loader.next()

// 卸载UI
loader.next()

Class

class对象

let methodName = "getArea";
class Square{
  constructor(length) {
    // ...
  }

  [methodName]() {
    // ...
  }
}

ES6的class不存在变量提升。

class继承

eg:

class allClass {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }

  say(sth) {
    console.log(sth)
  }
}

class myClass extends allClass {
  constructor(x, y) {
    super()
    this.nice = 'ok'
  }

  get prop() {
    return this.nice
  }

  set prop(value) {
    this.nice = value
    console.log('setter:' + value);
  }
}

var b = new myClass();
console.log(b.prop)
b.prop = 'nice';
console.log(b.prop)

b.say('right');

静态属性(只有babel支持,ES6提案)

用法如下:

class allClass {
  defaultWords =  'what are you saying';
}

Module

ES6的模块自动采用严格模式

结果导致:

  • 变量必须声明后再使用
  • 函数的参数不能有同名属性,否则报错
  • 不能使用with语句
  • 不能对只读属性赋值,否则报错
  • 不能使用前缀0表示八进制数,否则报错
  • 不能删除不可删除的属性,否则报错
  • 不能删除变量delete prop,会报错,只能删除属性delete global[prop]
  • eval不会在它的外层作用域引入变量
  • eval和arguments不能被重新赋值
  • arguments不会自动反映函数参数的变化
  • 不能使用arguments.callee
  • 不能使用arguments.caller
  • 禁止this指向全局对象
  • 不能使用fn.caller和fn.arguments获取函数调用的堆栈
  • 增加了保留字(比如protected、static和interface)

import && export

<!-- import -->
import { stat, exists, readFile } from 'fs';

<!-- export -->
var firstName = 'Michael';
var lastName = 'Jackson';
var year = 1958;

export {firstName, lastName, year};

代码风格

要写好ES6,可以看看这些规范:编程风格

添加评论