欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

ECMAScript6 新特性范例大全

程序员文章站 2022-07-22 16:38:12
ecmascript6(ecmascript 2015 ,es5,es2016)技术已经在前端圈子很流行了,他给前端开发人员带来了很多惊喜,提供的语法糖使复杂的操作变得...

ECMAScript6 新特性范例大全

ecmascript6(ecmascript 2015 ,es5,es2016)技术已经在前端圈子很流行了,他给前端开发人员带来了很多惊喜,提供的语法糖使复杂的操作变得简单。

本文没有详细描述这些新特性,因为网上都已经有很多相关的介绍了。主要针对es6 新特性收集了相关范例代码,他可以让你快速了解这个新的javascript规范。

箭头函数

function() 函数的简写表示法,但它不绑定 this

var odds = evens.map(v => v + 1); // no parentes and no brackets
var nums = evens.map((v, i) => v + i);
var pairs = evens.map(v => ({even: v, odd: v + 1}));

// statement bodies
nums.foreach(v => {
 if (v % 5 === 0)
  fives.push(v);
});

this 是如何工作的?

var object = {
  name: "name", 
  arrowgetname: () => this.name,
  regulargetname: function() { return this.name },
  arrowgetthis: () => this,
  regulargetthis: function() { return this }
}

console.log(this.name)
console.log(object.arrowgetname());
console.log(object.arrowgetthis());
console.log(this)
console.log(object.regulargetname());
console.log(object.regulargetthis());

结果:

this.name -> 
object.arrowgetname() -> 
object.arrowgetthis() -> [object window]
this -> [object window]
object.regulargetname() -> name
object.regulargetthis() -> {"name":"name"}

classes(类)

我们知道“真正”语言中的类(classes)。在 es6 中类(classes)其实是原型继承的语法糖。

class skinnedmesh extends three.mesh {
 constructor(geometry, materials) {
  super(geometry, materials);

  this.idmatrix = skinnedmesh.defaultmatrix();
  this.bones = [];
  this.bonematrices = [];
  //...
 }
 update(camera) {
  //...
  super.update();
 }
 get bonecount() {
  return this.bones.length;
 }
 set matrixtype(matrixtype) {
  this.idmatrix = skinnedmesh[matrixtype]();
 }
 static defaultmatrix() {
  return new three.matrix4();
 }
}

lebab.io

增强的对象字面量

var theprotoobj = {
 tostring: function() {
  return "the protoobject to string"
 }
}

var handler = () => "handler"


var obj = {
  // __proto__
  __proto__: theprotoobj,

  // shorthand for ‘handler: handler'
  handler,

  // methods
  tostring() {

   // super calls
   return "d " + super.tostring();
  },

  // computed (dynamic) property names
  [ "prop_" + (() => 42)() ]: 42
};

console.log(obj.handler)
console.log(obj.handler())
console.log(obj.tostring())
console.log(obj.prop_42)

结果:

obj.handler -> () => "handler"
obj.handler() -> handler
obj.tostring() -> d the protoobject to string
obj.prop_42 -> 42

字符串插值

字符串插值的好语法

字符串插值

var name = "bob", time = "today";

var multiline = `this

line

spans multiple

lines`


console.log(`hello ${name},how are you ${time}?`)
console.log(multiline)

结果:

`hello ${name},how are you ${time}?` -> hello bob,how are you today?
multiline -> this line spans multiple lines

解构 destructuring

愚人码头注:列表匹配

// list "matching"
var [a, , b] = [1,2,3];
console.log(a)
console.log(b)

结果:

a -> 1
b -> 3

对象也能很好的解构

nodes = () => { return {op: "a", lhs: "b", rhs: "c"}}
var { op: a, lhs: b , rhs: c } = nodes()
console.log(a)
console.log(b)
console.log(c)

结果:

a -> a
b -> b
c -> c

使用速记表示法。

nodes = () => { return {lhs: "a", op: "b", rhs: "c"}}

// binds `op`, `lhs` and `rhs` in scope
var {op, lhs, rhs} = nodes()

console.log(op)
console.log(lhs)
console.log(rhs)

结果:

op -> b
lhs -> a
rhs -> c

可在参数位置使用

function g({name: x}) {
 return x
}

function m({name}) {
 return name
}

console.log(g({name: 5}))
console.log(m({name: 5}))

结果:

g({name: 5}) -> 5
m({name: 5}) -> 5

故障弱化解构

var [a] = []
var [b = 1] = []
var c = [];
console.log(a)
console.log(b);
console.log(c);

结果:

a -> undefined
b -> 1
c -> []

参数默认值(default)

function f(x, y=12) {
 return x + y;
}

console.log(f(3))
console.log(f(3,2))

结果:

f(3) -> 15
f(3,2) -> 5

扩展(spread)

在函数中:

function f(x, y, z) {
 return x + y + z;
}
// 传递数组的每个元素作为参数
console.log(f(...[1,2,3]))

结果:

f(...[1,2,3]) -> 6

在数组中:

var parts = ["shoulders", "knees"];
var lyrics = ["head", ...parts, "and", "toes"]; 

console.log(lyrics)

结果:

lyrics -> ["head","shoulders","knees","and","toes"]

扩展 + 对象字面量

我们可以使用这个创造很酷的对象。

let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
console.log(x); // 1
console.log(y); // 2
console.log(z); // { a: 3, b: 4 }

// spread properties
let n = { x, y, ...z };
console.log(n); // { x: 1, y: 2, a: 3, b: 4 }
console.log(obj)

可惜的是它还不支持:

npm install --save-dev babel-plugin-transform-object-rest-spread

rest

我们可以使用 rest 操作符来允许无限参数。

function demo(part1, ...part2) {
  return {part1, part2}
}

console.log(demo(1,2,3,4,5,6))

结果:

demo(1,2,3,4,5,6) -> {"part1":1,"part2":[2,3,4,5,6]}

let

let是新的var。 因为它有块级作用域。

{
  var globalvar = "from demo1"
}

{
  let globallet = "from demo2";
}

console.log(globalvar)
console.log(globallet)

结果:

globalvar -> from demo1
globallet -> referenceerror: globallet is not defined

但是,它不会向window分配任何内容:

let me = "go"; // 全局作用域
var i = "able"; // 全局作用域

console.log(window.me); 
console.log(window.i);

结果:

window.me -> undefined
window.i -> able

不能使用let重新声明一个变量:

let me = "foo";
let me = "bar"; 
console.log(me);

结果:

syntaxerror: identifier 'me' has already been declared
var me = "foo";
var me = "bar"; 
console.log(me)

结果:

me -> bar

const

const 是只读变量。

const a = "b"
a = "a"

结果:

typeerror: assignment to constant variable.

应该注意,const 对象仍然可以被改变的。

const a = { a: "a" }
a.a = "b"
console.log(a)

结果:

a -> {"a":"b"}

for..of

迭代器的新类型,可以替代for..in。 它返回的是值而不是keys

let list = [4, 5, 6];

console.log(list)

for (let i in list) {
  console.log(i);
}

结果:

list -> [4,5,6]
i -> 0
i -> 1
i -> 2
let list = [4, 5, 6];

console.log(list)


for (let i of list) {
  console.log(i); 
}

结果:

list -> [4,5,6]
i -> 4
i -> 5
i -> 6

迭代器(iterators)

迭代器是一个比数组更动态的类型。

let infinite = {
 [symbol.iterator]() {
  let c = 0;
  return {
   next() {
    c++;
    return { done: false, value: c }
   }
  }
 }
}

console.log("start");

for (var n of infinite) {
 // truncate the sequence at 1000
 if (n > 10)
  break;
 console.log(n);
}

结果:

"start" -> start
n -> 1
n -> 2
n -> 3
n -> 4
n -> 5
n -> 6
n -> 7
n -> 8
n -> 9
n -> 10

使用typescript,我们可以看到它接口的样子:

interface iteratorresult {
 done: boolean;
 value: any;
}
interface iterator {
 next(): iteratorresult;
}
interface iterable {
 [symbol.iterator](): iterator
}

生成器(generators)

生成器创建迭代器,并且比迭代器更具动态性。他们不必以相同的方式跟踪状态 并不支持 done 的概念。

var infinity = {
 [symbol.iterator]: function*() {
  var c = 1;
  for (;;) {  
   yield c++;
  }
 }
}

console.log("start")
for (var n of infinity) {
 // truncate the sequence at 1000
 if (n > 10)
  break;
 console.log(n);
}

结果:

"start" -> start
n -> 1
n -> 2
n -> 3
n -> 4
n -> 5
n -> 6
n -> 7
n -> 8
n -> 9
n -> 10

使用typescript 再次显示接口:

interface generator extends iterator {
  next(value?: any): iteratorresult;
  throw(exception: any);
}

function* iterators and generator

一个产量的例子*

function* anothergenerator(i) {
 yield i + 1;
 yield i + 2;
 yield i + 3;
}

function* generator(i) {
 yield i;
 yield* anothergenerator(i);
 yield i + 10;
}

var gen = generator(10);

console.log(gen.next().value); 
console.log(gen.next().value); 
console.log(gen.next().value); 
console.log(gen.next().value); 
console.log(gen.next().value);

结果:

gen.next().value -> 10
gen.next().value -> 11
gen.next().value -> 12
gen.next().value -> 13
gen.next().value -> 20

unicode

es6 为unicode 提供了更好的支持。

var regex = new regexp('\u{61}', 'u');

console.log(regex.unicode)
console.log("\ud842\udfd7")
console.log("\ud842\udfd7".codepointat())

结果:

regex.unicode -> true
"" -> 
"".codepointat() -> 134103

模块和模块加载器

原生支持模块。

import defaultmember from "module-name";
import * as name from "module-name";
import { member } from "module-name";
import { member as alias } from "module-name";
import { member1 , member2 } from "module-name";
import { member1 , member2 as alias2 , [...] } from "module-name";
import defaultmember, { member [ , [...] ] } from "module-name";
import defaultmember, * as name from "module-name";
import "module-name";
export { name1, name2, …, namen };
export { variable1 as name1, variable2 as name2, …, namen };
export let name1, name2, …, namen; // also var
export let name1 = …, name2 = …, …, namen; // also var, const

export expression;
export default expression;
export default function (…) { … } // also class, function*
export default function name1(…) { … } // also class, function*
export { name1 as default, … };

export * from …;
export { name1, name2, …, namen } from …;
export { import1 as name1, import2 as name2, …, namen } from …;

import export

set

set 为数学对应,其中所有项目都是唯一的。对于知道sql的人来说,这相当于distinct

var set = new set();
set.add("potato").add("tomato").add("tomato");
console.log(set.size)
console.log(set.has("tomato"))

for(var item of set) {
  console.log(item)
}

结果:

set.size -> 2
set.has("tomato") -> true
item -> potato
item -> tomato

set

weakset

weakset对象允许您在集合中存储弱持有的对象。没有引用的对象将被垃圾回收。

var item = { a:"potato"}
var set = new weakset();
set.add({ a:"potato"}).add(item).add({ a:"tomato"}).add({ a:"tomato"});
console.log(set.size)
console.log(set.has({a:"tomato"}))
console.log(set.has(item))

for(let item of set) {
  console.log(item)
}

结果:

set.size -> undefined
set.has({a:"tomato"}) -> false
set.has(item) -> true
typeerror: set[symbol.iterator] is not a function

weakset

map

map 也称为词典。

var map = new map();
map.set("potato", 12);
map.set("tomato", 34);

console.log(map.get("potato"))


for(let item of map) {
  console.log(item)
}


for(let item in map) {
  console.log(item)
}

结果:

map.get("potato") -> 12
item -> ["potato",12]
item -> ["tomato",34]

可以使用除字符串之外的其他类型。

var map = new map();
var key = {a: "a"}
map.set(key, 12);


console.log(map.get(key))
console.log(map.get({a: "a"}))

结果:

map.get(key) -> 12
map.get({a: "a"}) -> undefined

map

weakmap

使用键的对象,并且只保留对键的弱引用。

var wm = new weakmap();

var o1 = {}
var o2 = {}
var o3 = {}


wm.set(o1, 1);
wm.set(o2, 2);
wm.set(o3, {a: "a"});
wm.set({}, 4);

console.log(wm.get(o2));
console.log(wm.has({}))

delete o2;

console.log(wm.get(o3));

for(let item in wm) {
  console.log(item)
}


for(let item of wm) {
  console.log(item)
}

结果:

wm.get(o2) -> 2
wm.has({}) -> false
wm.get(o3) -> {"a":"a"}
typeerror: wm[symbol.iterator] is not a function

weakmap

代理(proxy)

代理可以用来改变对象的行为。 它们允许我们定义 trap 。

var obj = function profanitygenerator() {
  return {
    words: "horrible words"  
  }
}()

var handler = function censoringhandler() {
    return {
    get: function (target, key) {
      return target[key].replace("horrible", "nice");
    },
  }

}()

var proxy = new proxy(obj, handler);

console.log(proxy.words);

结果:

proxy.words -> nice words

提供以下 trap :

var handler =
{
 get:...,
 set:...,
 has:...,
 deleteproperty:...,
 apply:...,
 construct:...,
 getownpropertydescriptor:...,
 defineproperty:...,
 getprototypeof:...,
 setprototypeof:...,
 enumerate:...,
 ownkeys:...,
 preventextensions:...,
 isextensible:...
}

proxy

symbols

symbols 是一个新类型。 可用于创建匿名属性。

var typesymbol = symbol("type");

class pet {

 constructor(type) {

  this[typesymbol] = type;

 }
 gettype() {
   return this[typesymbol];
 }

}


var a = new pet("dog");
console.log(a.gettype());
console.log(object.getownpropertynames(a))


console.log(symbol("a") === symbol("a"))

结果:

a.gettype() -> dog
object.getownpropertynames(a) -> []
symbol("a") === symbol("a") -> false

更多信息

可继承内置函数

我们现在可以继承原生类。

class customarray extends array {

}

var a = new customarray();

a[0] = 2
console.log(a[0])

结果:

a[0] -> 2

不能使用数组的代理(proxy)来覆盖getter函数。

新类库

各种新的方法和常量。

console.log(number.epsilon)
console.log(number.isinteger(infinity))
console.log(number.isnan("nan"))

console.log(math.acosh(3))
console.log(math.hypot(3, 4))
console.log(math.imul(math.pow(2, 32) - 1, math.pow(2, 32) - 2))

console.log("abcde".includes("cd") )
console.log("abc".repeat(3) )


console.log(array.of(1, 2, 3) )
console.log([0, 0, 0].fill(7, 1) )
console.log([1, 2, 3].find(x => x == 3) )
console.log([1, 2, 3].findindex(x => x == 2)) 
console.log([1, 2, 3, 4, 5].copywithin(3, 0)) 
console.log(["a", "b", "c"].entries() )
console.log(["a", "b", "c"].keys() )
console.log(["a", "b", "c"].values() )

console.log(object.assign({}, { origin: new point(0,0) }))

结果:

number.epsilon -> 2.220446049250313e-16
number.isinteger(infinity) -> false
number.isnan("nan") -> false
math.acosh(3) -> 1.7627471740390859
math.hypot(3, 4) -> 5
math.imul(math.pow(2, 32) - 1, math.pow(2, 32) - 2) -> 2
"abcde".includes("cd") -> true
"abc".repeat(3) -> abcabcabc
array.of(1, 2, 3) -> [1,2,3]
[0, 0, 0].fill(7, 1) -> [0,7,7]
[1, 2, 3].find(x => x == 3) -> 3
[1, 2, 3].findindex(x => x == 2) -> 1
[1, 2, 3, 4, 5].copywithin(3, 0) -> [1,2,3,1,2]
["a", "b", "c"].entries() -> {}
["a", "b", "c"].keys() -> {}
["a", "b", "c"].values() -> typeerror: ["a","b","c"].values is not a function
object.assign({}, { origin: new point(0,0) }) -> referenceerror: point is not defined

文档: number, math, array.from, array.of, array.prototype.copywithin, object.assign

二进制和八进制

二进制和八进制数字的字面量。

console.log(0b11111)
console.log(0o2342)

console.log(0xff); // also in es5

结果:

0b11111 -> 31
0o2342 -> 1250
0xff -> 255

promises

异步编程。

var p1 = new promise((resolve, reject) => {
 settimeout(() => resolve("1"), 101)
})
var p2 = new promise((resolve, reject) => {
 settimeout(() => resolve("2"), 100)
})

promise.race([p1, p2]).then((res) => {
  console.log(res)
})

promise.all([p1, p2]).then((res) => {
  console.log(res)
})

结果:

res -> 2
res -> ["1","2"]

快速的 promise

var p1 = promise.resolve("1")
var p2 = promise.reject("2")

promise.race([p1, p2]).then((res) => {
  console.log(res)
})

结果:

res -> 1

快速失败

如果一个 promise 失败,allrace也将 reject(拒绝)。

var p1 = new promise((resolve, reject) => {
 settimeout(() => resolve("1"), 1001)
})
var p2 = new promise((resolve, reject) => {
 settimeout(() => reject("2"), 1)
})

promise.race([p1, p2]).then((res) => {
  console.log("success" + res)
}, res => {
  console.log("error " + res)
})

promise.all([p1, p2]).then((res) => {
  console.log("success" + res)
}, res => {
  console.log("error " + res)
})

结果:

"error " + res -> error 2
"error " + res -> error 2

更多信息

反射(reflect)

新类型的元编程与新的api现有的还有一些新的方法。

var z = {w: "super hello"}
var y = {x: "hello", __proto__: z};

console.log(reflect.getownpropertydescriptor(y, "x"));
console.log(reflect.has(y, "w"));
console.log(reflect.ownkeys(y, "w"));

console.log(reflect.has(y, "x"));
console.log(reflect.deleteproperty(y,"x"))
console.log(reflect.has(y, "x"));

结果:

reflect.getownpropertydescriptor(y, "x") -> {"value":"hello","writable":true,"enumerable":true,"configurable":true}
reflect.has(y, "w") -> true
reflect.ownkeys(y, "w") -> ["x"]
reflect.has(y, "x") -> true
reflect.deleteproperty(y,"x") -> true
reflect.has(y, "x") -> false

更多信息

尾调用(tail call)优化

尾调用的概念非常简单,一句话就能说清楚,就是指某个函数的最后一步是调用另一个函数。

es6可以确保尾调用不会造成堆栈溢出。 (不是所有的实现工作)。

function factorial(n, acc = 1) {
  if (n <= 1) return acc; 
  return factorial(n - 1, n * acc);
}
console.log(factorial(10))
console.log(factorial(100))
console.log(factorial(1000))
console.log(factorial(10000))
console.log(factorial(100000))
console.log(factorial(1000000))

结果:

factorial(10) -> 3628800
factorial(100) -> 9.332621544394418e+157
factorial(1000) -> infinity
factorial(10000) -> infinity
factorial(100000) -> rangeerror: maximum call stack size exceeded
factorial(1000000) -> rangeerror: maximum call stack size exceeded

原文:es6 features