ES6初识
ES6 简述
就是新一代的Javascript标准,js引擎按照这个标准来实现Javascript这个语言,不需要把它想得太神秘,太高级,对于我们js的工程师而言,熟悉新的特性及语法,在实践过程中,提高工作效率,把项目搞好就行。当然,还有一点就像[我微博]里提到的,如果再不学习,可能过个一两年,等ES6普及开来了,一些库的代码你可能都读不懂了。
兼容性
由于今年才定稿,早期某些特性定稿的时候已经有『先进的浏览器』实现了部分特性,浏览器支持还不是太完整,而服务器端更激进一些,很多特性已经支持了,详细的特性支持列表,建议参考
http://kangax.github.io/compat-table/es6/
以后会是每年制定一个标准,所以也以年号来定,ES6也叫ES2015
关于学习的一点感触
语言只是工具,新特性如果能提高工资效率那必然是好特性,如果不能,然并卵 loadsh和underscore的存在,只能说明语言本身有很多未完善的地方,等到语言真的完善了,它们也就退出历史舞台了。
本文自带了babel,在代码区域单击,同时打开开发者工具,可以在控制台里看到输出
或者可以在我弄的这个网页版的repl里运行代码,在控制台里看结果
似曾相似
Object.assign
类似于jQuery的$.extend,但是功能比较弱,只是浅拷贝,用处很多,也可以克隆对象
let a = {a:1}
let b = {a:2}
let c = {c:{d:1}}
console.log(Object.assign(a, b, c))
c.c.d = 2
Array.prototype.find
查找到第一个符合条件的值比遍历更好用
console.log([1,3,4,2].find(function(v){
return v > 3
})) //4
Array.prototype.filter
查找到所有符合条件的值
console.log([1,3,4,2].filter(function(v){
return v > 2
})) //[3,4]
String.prototype.includes
String.prototype.startsWith
String.prototype.endsWith
三个方法都是indexOf的加强版,其中的查询字符串只不支持正则,如果是正则会抛出错误
console.log("hello".startsWith("ello", 1)) // true
console.log("hello".endsWith("hell", 4) ) // true, 针对前4个字符
console.log("hello".includes("ell") ) // true
console.log("hello".includes("ell", 1) ) // true
console.log("hello".includes("ell", 2) ) // false
字符串模板
告别手工拼接字符串
let x = 123
console.log(`${x}`) //123
${}
内是标准的js语法
let x = 123
let y = 234
console.log(`${(x+y).toString(16)}`) //165
多行字符串
let name = 'hubo.hb'
let html = `
<div id="header">
${name}
</div>
`
console.log(html)
标签模板
一个可以干预模板翻译过程的函数
function toUpper(s) {
return s.toString().toUpperCase()
}
console.log(toUpper`Go up!`) //'GO UP!'
第一个参数是除了替换的字符串的数组,剩下的参数是所有替换出来的值
function valuesOnly(stringsArray, ...valuesArray) {
return valuesArray.join('; ')
}
var one = 1
var two = 2
console.log(valuesOnly`uno=${one}, dos=${two}, tres=?`) //'1; 2'
let, const
let is the new var,块级作用域, 区块中存在let和const命令,凡是在声明之前就使用这些命令,就会报错。 不会有变量提升,重复定义会报错
'use strict';
if (true) {
let a = 1
if (a) {
console.log(a) //ReferenceError: a is not defined
let a = 2
}
}
const定义过的变量不能修改(修改无效),同样不会有变量提升,重复定义会报错
const a = 1
a = 2 //TypeError: Assignment to constant variable.
箭头函数
减少函数输入,this的自动绑定
var func = () => 'I return 1' //无参数的情况
console.log(func()) //I return 1
单个参数时可以省略参数括号
var odds = evens.map(v => v + 1)
如果想使用比较复杂的函数体,可以用{}
包起来
nums.forEach(v => {
if (v % 5 === 0)
fives.push(v)
})
如果默认返回一个对象,需要用()
把对象包裹起来
var nums = [1, 2, 3, 4]
console.log(nums.map(v => ({v}))) //[ { v: 1 }, { v: 2 }, { v: 3 }, { v: 4 } ]
遍历操作常用
console.log([1,2,3,4].map(v => v*2)) //单参的情况
- 不能当作构造函数
- 不能改变this
- 不可以使用arguments对象
let o = {
render(){
setTimeout(()=> this.showIt(), 100)
},
showIt(){
console.log('I show')
}
}
o.render()
更方便的对象字面量
const x = 1
const y = 2
console.log({x, y}) //{x:1, y:2}
属性表达式
const x = 1
const y = 2
console.log({['xy'+ x + y]:`${x + y}`})
同时对象字面量也支持父级调用
var obj = {
toString() {
return "d " + super.toString()
}
}
rest参数和展开符(…)
函数定义的时候使用…变量名,必须是最后一个参数,函数体内通过变量获取参数数组
const fn = (...rest) => rest.join()
console.log(fn(1, 2))
…把数组转化为参数序列,也可以
console.log([...'hello']) //["h", "e", "l", "l", "o"]
解构赋值
模式匹配批量赋值,数组,字符串,对象均可
const [a, b] = [1, 2]
console.log(a) //1
console.log(b) //2
const [c, d] = [...[1, 2]]
console.log(c) //1
console.log(d) //2
const [a, b, ...end] = [1, 2, 3, 4]
console.log(a, b, end) //1 2 [3,4]
const [h,...ends] = 'hello'
console.log(h, ends) //h ["e", "l", "l", "o"]
快速提取JSON里的值
var jsonData = {
id: 42,
status: "OK",
data: [867, 5309]
}
let { id, status, data: [,secondData] } = jsonData;
console.log(id, status, secondData)// 42 OK 5309
同样可以用在函数参数里
function g({name: x}) {
console.log(x)
}
g({name: 5}) // 5
可以使用默认值
let [a = 1] = []
console.log(a === 1) // true
参数默认值
传入的参数为undefined时,使用默认值
let number = (int = 0) => int;
console.log(number()) //0
对象参数默认值
function fetch(url, { body = '', method = 'GET', headers = {} } = {}){
console.log(method)
}
fetch('http://jser.me') //GET
fetch('http://jser.me', {}) //GET
fetch('http://jser.me', {method:'POST'}) //POST
参数省略只能从后向前省
类
本质上类是一个语法糖,可以使用ES5来模拟,它支持原型继承,父级调用,实例方法,静态方法和构造函数
class Point extends Sharp {
constructor(x, y) {
super(x, y)
this.x = x;
this.y = y;
}
update(x, y) {
}
static someMethod(){
return 'call'
}
toString() {
return '('+this.x+', '+this.y+')';
}
}
Iterators和for of
迭代对象可以让我们方便的使用for of进行遍历,字符串,数组,Set, Map都可以使用for of进行遍历
var s = '123abc'
for (let n of s) {
console.log(n) //1 2 3 a b c
}
自定义一个对象的迭代
let fibonacci = {
[Symbol.iterator]() {
let pre = 0, cur = 1
return {
next() {
[pre, cur] = [cur, pre + cur]
return { done: false, value: cur }
}
}
}
}
for (var n of fibonacci) {
if (n > 1000) break
console.log(n)
}
模块
与nodejs的cmd定义有较大的区别
// lib/math.js
export function sum(x, y) {
return x + y
}
export const pi = 3.141593
// app.js
import * as math from "lib/math"
alert("2π = " + math.sum(math.pi, math.pi))
默认导出 export default xxx
// lib/mathplusplus.js
export * from "lib/math"
export const e = 2.71828182846
export default function(x) {
return Math.log(x)
}
// app.js
import ln, {pi, e} from "lib/mathplusplus"
alert("2π = " + ln(e)*pi*2)
Proxy
Proxy我个人理解提供了一个对象行为钩子,我们可以用来做拦截等事情
var target = {}
var handler = {
get: function (receiver, name) {
return `Hello, ${name}!`
}
}
var p = new Proxy(target, handler)
console.log(p.world)
handler里可以用来挂的对象属性:
var handler =
{
get:...,
set:...,
has:...,
deleteProperty:...,
apply:...,
construct:...,
getOwnPropertyDescriptor:...,
defineProperty:...,
getPrototypeOf:...,
setPrototypeOf:...,
enumerate:...,
ownKeys:...,
preventExtensions:...,
isExtensible:...
}
Promies
不需要多讲,比较简单,大家多用就行了,用多了会上瘾。
Map和Set
两种新引入的数据结构,Map的键可以为任意对象,Map是Object的补充 Set可以理解为成员唯一的数组
总结
JS越来越完善,当然也越来越像JAVA。