mirror of
https://github.com/ruanyf/es6tutorial.git
synced 2025-05-24 18:32:22 +00:00
doc: add ES7 stage 3 features
This commit is contained in:
parent
0be4b18312
commit
40437de61a
@ -691,7 +691,7 @@ function* somethingAsync(x) {
|
||||
}
|
||||
```
|
||||
|
||||
上面的代码允许并发三个somethingAsync异步操作,等到它们全部完成,才会进行下一步。
|
||||
上面的代码允许并发三个`somethingAsync`异步操作,等到它们全部完成,才会进行下一步。
|
||||
|
||||
## async函数
|
||||
|
||||
@ -721,7 +721,7 @@ var gen = function* (){
|
||||
};
|
||||
```
|
||||
|
||||
写成 async 函数,就是下面这样。
|
||||
写成`async`函数,就是下面这样。
|
||||
|
||||
```javascript
|
||||
var asyncReadFile = async function (){
|
||||
@ -734,7 +734,7 @@ var asyncReadFile = async function (){
|
||||
|
||||
一比较就会发现,`async`函数就是将Generator函数的星号(`*`)替换成`async`,将`yield`替换成`await`,仅此而已。
|
||||
|
||||
`async`函数对 Generator 函数的改进,体现在以下三点。
|
||||
`async`函数对 Generator 函数的改进,体现在以下四点。
|
||||
|
||||
(1)内置执行器。Generator函数的执行必须靠执行器,所以才有了`co`模块,而`async`函数自带执行器。也就是说,`async`函数的执行,与普通函数一模一样,只要一行。
|
||||
|
||||
@ -752,6 +752,8 @@ var result = asyncReadFile();
|
||||
|
||||
进一步说,async函数完全可以看作多个异步操作,包装成的一个Promise对象,而`await`命令就是内部`then`命令的语法糖。
|
||||
|
||||
正常情况下,`await`命令后面是一个Promise对象,否则会被转成Promise。
|
||||
|
||||
### async函数的实现
|
||||
|
||||
async 函数的实现,就是将 Generator 函数和自动执行器,包装在一个函数里。
|
||||
@ -770,9 +772,9 @@ function fn(args){
|
||||
}
|
||||
```
|
||||
|
||||
所有的 async 函数都可以写成上面的第二种形式,其中的 spawn 函数就是自动执行器。
|
||||
所有的`async`函数都可以写成上面的第二种形式,其中的 spawn 函数就是自动执行器。
|
||||
|
||||
下面给出 spawn 函数的实现,基本就是前文自动执行器的翻版。
|
||||
下面给出`spawn`函数的实现,基本就是前文自动执行器的翻版。
|
||||
|
||||
```javascript
|
||||
function spawn(genF) {
|
||||
@ -798,11 +800,11 @@ function spawn(genF) {
|
||||
}
|
||||
```
|
||||
|
||||
async 函数是非常新的语法功能,新到都不属于 ES6,而是属于 ES7。目前,它仍处于提案阶段,但是转码器 Babel 和 regenerator 都已经支持,转码后就能使用。
|
||||
`async`函数是非常新的语法功能,新到都不属于 ES6,而是属于 ES7。目前,它仍处于提案阶段,但是转码器`Babel`和`regenerator`都已经支持,转码后就能使用。
|
||||
|
||||
### async 函数的用法
|
||||
|
||||
同Generator函数一样,async函数返回一个Promise对象,可以使用then方法添加回调函数。当函数执行的时候,一旦遇到 await 就会先返回,等到触发的异步操作完成,再接着执行函数体内后面的语句。
|
||||
同Generator函数一样,`async`函数返回一个Promise对象,可以使用`then`方法添加回调函数。当函数执行的时候,一旦遇到`await`就会先返回,等到触发的异步操作完成,再接着执行函数体内后面的语句。
|
||||
|
||||
下面是一个例子。
|
||||
|
||||
@ -818,7 +820,7 @@ getStockPriceByName('goog').then(function (result){
|
||||
});
|
||||
```
|
||||
|
||||
上面代码是一个获取股票报价的函数,函数前面的async关键字,表明该函数内部有异步操作。调用该函数时,会立即返回一个Promise对象。
|
||||
上面代码是一个获取股票报价的函数,函数前面的`async`关键字,表明该函数内部有异步操作。调用该函数时,会立即返回一个`Promise`对象。
|
||||
|
||||
下面的例子,指定多少毫秒后输出一个值。
|
||||
|
||||
@ -839,6 +841,22 @@ asyncPrint('hello world', 50);
|
||||
|
||||
上面代码指定50毫秒以后,输出"hello world"。
|
||||
|
||||
Async函数有多种使用形式。
|
||||
|
||||
```javascript
|
||||
// 函数声明
|
||||
async function foo() {}
|
||||
|
||||
// 函数表达式
|
||||
const foo = async function () {};
|
||||
|
||||
// 对象的方法
|
||||
let obj = { async foo() {} }
|
||||
|
||||
// 箭头函数
|
||||
const foo = async () => {};
|
||||
```
|
||||
|
||||
### 注意点
|
||||
|
||||
第一点,`await`命令后面的Promise对象,运行结果可能是rejected,所以最好把`await`命令放在`try...catch`代码块中。
|
||||
|
198
docs/object.md
198
docs/object.md
@ -729,6 +729,13 @@ Object.values(obj) // []
|
||||
|
||||
上面代码中,`Object.create`方法的第二个参数添加的对象属性(属性`p`),如果不显式声明,默认是不可遍历的。`Object.values`不会返回这个属性。
|
||||
|
||||
`Object.values`会过滤属性名为Symbol值的属性。
|
||||
|
||||
```javascript
|
||||
Object.entries({ [Symbol()]: 123, foo: 'abc' });
|
||||
// ['abc']
|
||||
```
|
||||
|
||||
如果`Object.values`方法的参数是一个字符串,会返回各个字符组成的一个数组。
|
||||
|
||||
```javascript
|
||||
@ -757,6 +764,26 @@ Object.entries(obj)
|
||||
|
||||
除了返回值不一样,该方法的行为与`Object.values`基本一致。
|
||||
|
||||
如果原对象的属性名是一个Symbol值,该属性会被省略。
|
||||
|
||||
```javascript
|
||||
Object.entries({ [Symbol()]: 123, foo: 'abc' });
|
||||
// [ [ 'foo', 'abc' ] ]
|
||||
```
|
||||
|
||||
上面代码中,原对象有两个属性,`Object.entries`只输出属性名非Symbol值的属性。将来可能会有`Reflect.ownEntries()`方法,返回对象自身的所有属性。
|
||||
|
||||
`Object.entries`的基本用途是遍历对象的属性。
|
||||
|
||||
```javascript
|
||||
let obj = { one: 1, two: 2 };
|
||||
for (let [k, v] of Object.entries(obj)) {
|
||||
console.log(`${JSON.stringify(k)}: ${JSON.stringify(v)}`);
|
||||
}
|
||||
// "one": 1
|
||||
// "two": 2
|
||||
```
|
||||
|
||||
`Object.entries`方法的一个用处是,将对象转为真正的`Map`结构。
|
||||
|
||||
```javascript
|
||||
@ -896,3 +923,174 @@ let runtimeError = {
|
||||
```javascript
|
||||
let emptyObject = { ...null, ...undefined }; // 不报错
|
||||
```
|
||||
|
||||
## Object.getOwnPropertyDescriptors()
|
||||
|
||||
ES5有一个`Object.getOwnPropertyDescriptor`方法,返回某个对象属性的描述对象(descriptor)。
|
||||
|
||||
```javascript
|
||||
var obj = { p: 'a' };
|
||||
|
||||
Object.getOwnPropertyDescriptor(obj, 'p')
|
||||
// Object { value: "a",
|
||||
// writable: true,
|
||||
// enumerable: true,
|
||||
// configurable: true
|
||||
// }
|
||||
```
|
||||
|
||||
ES7有一个提案,提出了`Object.getOwnPropertyDescriptors`方法,返回指定对象所有自身属性(非继承属性)的描述对象。
|
||||
|
||||
```javascript
|
||||
const obj = {
|
||||
foo: 123,
|
||||
get bar() { return 'abc' },
|
||||
};
|
||||
|
||||
Object.getOwnPropertyDescriptors(obj)
|
||||
// { foo:
|
||||
// { value: 123,
|
||||
// writable: true,
|
||||
// enumerable: true,
|
||||
// configurable: true },
|
||||
// bar:
|
||||
// { get: [Function: bar],
|
||||
// set: undefined,
|
||||
// enumerable: true,
|
||||
// configurable: true } }
|
||||
```
|
||||
|
||||
`Object.getOwnPropertyDescriptors`方法返回一个对象,所有原对象的属性名都是该对象的属性名,对应的属性值就是该属性的描述对象。
|
||||
|
||||
该方法的实现非常容易。
|
||||
|
||||
```javascript
|
||||
function getOwnPropertyDescriptors(obj) {
|
||||
const result = {};
|
||||
for (let key of Reflect.ownKeys(obj)) {
|
||||
result[key] = Object.getOwnPropertyDescriptor(obj, key);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
```
|
||||
|
||||
该方法的提出目的,主要是为了解决`Object.assign()`无法正确拷贝`get`属性和`set`属性的问题。
|
||||
|
||||
```javascript
|
||||
const source = {
|
||||
set foo(value) {
|
||||
console.log(value);
|
||||
}
|
||||
};
|
||||
|
||||
const target1 = {};
|
||||
Object.assign(target1, source);
|
||||
|
||||
Object.getOwnPropertyDescriptor(target1, 'foo')
|
||||
// { value: undefined,
|
||||
// writable: true,
|
||||
// enumerable: true,
|
||||
// configurable: true }
|
||||
```
|
||||
|
||||
上面代码中,`source`对象的`foo`属性的值是一个赋值函数,`Object.assign`方法将这个属性拷贝给`target1`对象,结果该属性的值变成了`undefined`。这是因为`Object.assign`方法总是拷贝一个属性的值,而不会拷贝它背后的赋值方法或取值方法。
|
||||
|
||||
这时,`Object.getOwnPropertyDescriptors`方法配合`Object.defineProperties`方法,就可以实现正确拷贝。
|
||||
|
||||
```javascript
|
||||
const source = {
|
||||
set foo(value) {
|
||||
console.log(value);
|
||||
}
|
||||
};
|
||||
|
||||
const target2 = {};
|
||||
Object.defineProperties(target2, Object.getOwnPropertyDescriptors(source));
|
||||
Object.getOwnPropertyDescriptor(target2, 'foo')
|
||||
// { get: undefined,
|
||||
// set: [Function: foo],
|
||||
// enumerable: true,
|
||||
// configurable: true }
|
||||
```
|
||||
|
||||
上面代码中,将两个对象合并的逻辑提炼出来,就是下面这样。
|
||||
|
||||
```javascript
|
||||
const shallowMerge = (target, source) => Object.defineProperties(
|
||||
target,
|
||||
Object.getOwnPropertyDescriptors(source)
|
||||
);
|
||||
```
|
||||
|
||||
`Object.getOwnPropertyDescriptors`方法的另一个用处,是配合`Object.create`方法,将对象属性克隆到一个新对象。这属于浅拷贝。
|
||||
|
||||
```javascript
|
||||
const clone = Object.create(Object.getPrototypeOf(obj),
|
||||
Object.getOwnPropertyDescriptors(obj));
|
||||
|
||||
// 或者
|
||||
|
||||
const shallowClone = (obj) => Object.create(
|
||||
Object.getPrototypeOf(obj),
|
||||
Object.getOwnPropertyDescriptors(obj)
|
||||
);
|
||||
```
|
||||
|
||||
上面代码会克隆对象`obj`。
|
||||
|
||||
另外,`Object.getOwnPropertyDescriptors`方法可以实现,一个对象继承另一个对象。以前,继承另一个对象,常常写成下面这样。
|
||||
|
||||
```javascript
|
||||
const obj = {
|
||||
__proto__: prot,
|
||||
foo: 123,
|
||||
};
|
||||
```
|
||||
|
||||
ES6规定`__proto__`只有浏览器要部署,其他环境不用部署。如果去除`__proto__`,上面代码就要改成下面这样。
|
||||
|
||||
```javascript
|
||||
const obj = Object.create(prot);
|
||||
obj.foo = 123;
|
||||
|
||||
// 或者
|
||||
|
||||
const obj = Object.assign(
|
||||
Object.create(prot),
|
||||
{
|
||||
foo: 123,
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
有了`Object.getOwnPropertyDescriptors`,我们就有了另一种写法。
|
||||
|
||||
```javascript
|
||||
const obj = Object.create(
|
||||
prot,
|
||||
Object.getOwnPropertyDescriptors({
|
||||
foo: 123,
|
||||
})
|
||||
);
|
||||
```
|
||||
|
||||
`Object.getOwnPropertyDescriptors`也可以用来实现Mixin(混入)模式。
|
||||
|
||||
```javascript
|
||||
let mix = (object) => ({
|
||||
with: (...mixins) => mixins.reduce(
|
||||
(c, mixin) => Object.create(
|
||||
c, Object.getOwnPropertyDescriptors(mixin)
|
||||
), object)
|
||||
});
|
||||
|
||||
// multiple mixins example
|
||||
let a = {a: 'a'};
|
||||
let b = {b: 'b'};
|
||||
let c = {c: 'c'};
|
||||
let d = mix(c).with(a, b);
|
||||
```
|
||||
|
||||
上面代码中,对象`a`和`b`被混入了对象`c`。
|
||||
|
||||
出于完整性的考虑,`Object.getOwnPropertyDescriptors`进入标准以后,还会有`Reflect.getOwnPropertyDescriptors`方法。
|
||||
|
@ -245,7 +245,7 @@ arr[-1] // c
|
||||
|
||||
上面代码中,数组的位置参数是`-1`,就会输出数组的倒数最后一个成员。
|
||||
|
||||
利用proxy,可以将读取属性的操作(`get`),转变为执行某个函数,从而实现属性的链式操作。
|
||||
利用Proxy,可以将读取属性的操作(`get`),转变为执行某个函数,从而实现属性的链式操作。
|
||||
|
||||
```javascript
|
||||
var pipe = (function () {
|
||||
@ -276,11 +276,46 @@ pipe(3).double.pow.reverseInt.get
|
||||
|
||||
上面代码设置Proxy以后,达到了将函数名链式使用的效果。
|
||||
|
||||
下面的例子则是利用`get`拦截,实现一个生成各种DOM节点的通用函数`dom`。
|
||||
|
||||
```javascript
|
||||
const el = dom.div({},
|
||||
'Hello, my name is ',
|
||||
dom.a({href: '//example.com'}, 'Mark'),
|
||||
'. I like:',
|
||||
dom.ul({},
|
||||
dom.li({}, 'The web'),
|
||||
dom.li({}, 'Food'),
|
||||
dom.li({}, '…actually that\'s it')
|
||||
)
|
||||
);
|
||||
|
||||
document.body.appendChild(el);
|
||||
|
||||
const dom = new Proxy({}, {
|
||||
get(target, property) {
|
||||
return function(attrs = {}, ...children) {
|
||||
const el = document.createElement(property);
|
||||
for (let prop of Object.keys(attrs)) {
|
||||
el.setAttribute(prop, attrs[prop]);
|
||||
}
|
||||
for (let child of children) {
|
||||
if (typeof child === 'string') {
|
||||
child = document.createTextNode(child);
|
||||
}
|
||||
el.appendChild(child);
|
||||
}
|
||||
return el;
|
||||
}
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### set()
|
||||
|
||||
`set`方法用来拦截某个属性的赋值操作。
|
||||
|
||||
假定Person对象有一个`age`属性,该属性应该是一个不大于200的整数,那么可以使用Proxy对象保证`age`的属性值符合要求。
|
||||
假定`Person`对象有一个`age`属性,该属性应该是一个不大于200的整数,那么可以使用`Proxy`保证`age`的属性值符合要求。
|
||||
|
||||
```javascript
|
||||
let validator = {
|
||||
@ -364,8 +399,8 @@ var handler = {
|
||||
|
||||
var p = new Proxy(target, handler);
|
||||
|
||||
p() === 'I am the proxy';
|
||||
// true
|
||||
p()
|
||||
// "I am the proxy"
|
||||
```
|
||||
|
||||
上面代码中,变量`p`是Proxy的实例,当它作为函数调用时(`p()`),就会被`apply`方法拦截,返回一个字符串。
|
||||
@ -387,7 +422,7 @@ proxy.call(null, 5, 6) // 22
|
||||
proxy.apply(null, [7, 8]) // 30
|
||||
```
|
||||
|
||||
上面代码中,每当执行`proxy`函数,就会被`apply`方法拦截。
|
||||
上面代码中,每当执行`proxy`函数(直接调用或`call`和`apply`调用),就会被`apply`方法拦截。
|
||||
|
||||
另外,直接调用`Reflect.apply`方法,也会被拦截。
|
||||
|
||||
|
@ -82,6 +82,8 @@
|
||||
- Sella Rafaeli, [Native JavaScript Data-Binding](http://www.sellarafaeli.com/blog/native_javascript_data_binding): 如何使用Object.observe方法,实现数据对象与DOM对象的双向绑定
|
||||
- Axel Rauschmayer, [`__proto__` in ECMAScript 6](http://www.2ality.com/2015/09/proto-es6.html)
|
||||
- Axel Rauschmayer, [Enumerability in ECMAScript 6](http://www.2ality.com/2015/10/enumerability-es6.html)
|
||||
- Axel Rauschmayer, [ES proposal: Object.getOwnPropertyDescriptors()](http://www.2ality.com/2016/02/object-getownpropertydescriptors.html)
|
||||
- TC39, [Object.getOwnPropertyDescriptors Proposal](https://github.com/tc39/proposal-object-getownpropertydescriptors)
|
||||
|
||||
## Proxy和Reflect
|
||||
|
||||
|
145
docs/simd.md
145
docs/simd.md
@ -1,5 +1,7 @@
|
||||
# SIMD 的用法
|
||||
|
||||
## 概述
|
||||
|
||||
SIMD是“Single Instruction/Multiple Data”的缩写,意为“单指令,多数据”。它是JavaScript操作CPU对应指令的接口,你可以看做这是一种不同的运算执行模式。与它相对的是SISD(“Single Instruction/Single Data”),即“单指令,单数据”。
|
||||
|
||||
SIMD的含义是使用一个指令,完成多个数据的运算;SISD的含义是使用一个指令,完成单个数据的运算,这是JavaScript的默认运算模式。显而易见,SIMD的执行效率要高于SISD,所以被广泛用于3D图形运算、物理模拟等运算量超大的项目之中。
|
||||
@ -31,3 +33,146 @@ var c = SIMD.Float32x4.add(a,b); // Float32x4[6, 8, 10, 12]
|
||||
上面代码之中,数组`a`和`b`的四个成员的各自相加,只用一条指令就完成了。因此,速度比上一种写法提高了4倍。
|
||||
|
||||
一次SIMD运算,可以处理多个数据,这些数据被称为“通道”(lane)。上面代码中,一次运算了四个数据,因此就是四个通道。
|
||||
|
||||
SIMD通常用于矢量运算。
|
||||
|
||||
```javascript
|
||||
v + w = 〈v1, …, vn〉+ 〈w1, …, wn〉
|
||||
= 〈v1+w1, …, vn+wn〉
|
||||
```
|
||||
|
||||
上面代码中,`v`和`w`是两个多元矢量。它们的加运算,在SIMD下是一个指令、而不是n个指令完成的,这就大大提高了效率。这对于3D动画、图像处理、信号处理、数值处理、加密等运算是非常重要的。
|
||||
|
||||
总得来说,SIMD是数据并行处理(parallelism)的一种手段。
|
||||
|
||||
## 数据类型
|
||||
|
||||
SIMD提供多种数据类型。
|
||||
|
||||
- Float32x4:四个32位浮点数
|
||||
- Float64x2:两个64位浮点数
|
||||
- Int32x4:四个32位整数
|
||||
- Int16x8:八个16位整数
|
||||
- Int8x16:十六个8位整数
|
||||
- Uint32x4:四个无符号的32位整数
|
||||
- Uint16x8:八个无符号的16位整数
|
||||
- Uint8x16:十六个无符号的8位整数
|
||||
- Bool32x4:四个32位布尔值
|
||||
- Bool16x8:八个16位布尔值
|
||||
- Bool8x16:十六个8位布尔值
|
||||
- Bool64x2:两个64位布尔值
|
||||
|
||||
每种数据类型都是一个方法,可以传入参数,生成对应的值。
|
||||
|
||||
```javascript
|
||||
var a = SIMD.Float32x4(1.0, 2.0, 3.0, 4.0);
|
||||
```
|
||||
|
||||
上面代码中,变量`a`就是一个128位、包含四个32位浮点数的值。
|
||||
|
||||
注意,这些数据类型方法都不是构造函数,前面不能加`new`,否则会报错。
|
||||
|
||||
```javascript
|
||||
var v = new SIMD.Float32x4(0,1,2,3);
|
||||
// TypeError: SIMD.Float32x4 is not a constructor
|
||||
```
|
||||
|
||||
每种数据类型都有一系列运算符,下面是其中的一些。
|
||||
|
||||
- float32x4.abs(v):返回`v`的绝对值
|
||||
- float32x4.neg(v):返回`v`的绝对值的负值
|
||||
- float32x4.sqrt(v):返回`v`的平方根
|
||||
- float32x4.add(v, w):`v`和`w`对应项的相加
|
||||
- float32x4.mul(v, w):`v`和`w`对应项的相乘
|
||||
- float32x4.equal(v, w):比较`v`和`w`对应项是否相等,返回的布尔值组成一个`uint32x4`的值
|
||||
|
||||
下面是一个`add`运算符的例子。
|
||||
|
||||
```javascript
|
||||
c[i] = SIMD.float32x4.add(a[i], b[i]);
|
||||
|
||||
// 或者
|
||||
|
||||
var tmp0 = a[i];
|
||||
var tmp1 = b[i];
|
||||
var tmp2 = SIMD.float32x4.add(tmp0, tmp1);
|
||||
c[i] = tmp2;
|
||||
```
|
||||
|
||||
此外,每种数据类型还有操作方法。
|
||||
|
||||
`getAt`方法返回指定位置的值。
|
||||
|
||||
```javascript
|
||||
var a = SIMD.float32x4(1.0, 2.0, 3.0, 4.0);
|
||||
var b = a.getAt(0); // 1.0
|
||||
```
|
||||
|
||||
`zero`方法可以将SIMD值清零。
|
||||
|
||||
```javascript
|
||||
var b = SIMD.float32x4.zero();
|
||||
```
|
||||
|
||||
上面代码中,变量`b`包含的四个32位浮点数全部是0.0。
|
||||
|
||||
`shuffle`方法根据指定模式,重新生成一个SIMD值。
|
||||
|
||||
```javascript
|
||||
var a = SIMD.float32x4(1.0, 2.0, 3.0, 4.0);
|
||||
var b = SIMD.float32x4.shuffle(a, SIMD.float32x4.XXYY);
|
||||
// [1.0, 1.0, 2.0, 2.0]
|
||||
|
||||
var c = SIMD.float32x4.shuffle(a, SIMD.float32x4.WWWW);
|
||||
// [4.0, 4.0, 4.0, 4.0]
|
||||
|
||||
var d = SIMD.float32x4.shuffle(a, SIMD.float32x4.WZYX);
|
||||
// [4.0, 3.0, 2.0, 1.0]
|
||||
```
|
||||
|
||||
下面是一个求平均值的例子。
|
||||
|
||||
```javascript
|
||||
function average(f32x4list) {
|
||||
var n = f32x4list.length;
|
||||
var sum = SIMD.float32x4.zero();
|
||||
for (int i = 0; i < n; i++) {
|
||||
sum = SIMD.float32x4.add(sum, f32x4list.getAt(i));
|
||||
}
|
||||
var total = sum.x + sum.y + sum.z + sum.w;
|
||||
return total / (n * 4);
|
||||
}
|
||||
```
|
||||
|
||||
## 二进制数组
|
||||
|
||||
SIMD可以与二进制数组结合,生成数组实例。
|
||||
|
||||
```javascript
|
||||
var _f64x2 = new Float64Array(_f32x4.buffer);
|
||||
var _i32x4 = new Int32Array(_f32x4.buffer);
|
||||
var _i16x8 = new Int16Array(_f32x4.buffer);
|
||||
var _i8x16 = new Int8Array(_f32x4.buffer);
|
||||
var _ui32x4 = new Uint32Array(_f32x4.buffer);
|
||||
var _ui16x8 = new Uint16Array(_f32x4.buffer);
|
||||
var _ui8x16 = new Uint8Array(_f32x4.buffer);
|
||||
```
|
||||
|
||||
下面是一些应用的例子。
|
||||
|
||||
```javascript
|
||||
// a 和 b 是float32x4数组实例
|
||||
function addArrays(a, b) {
|
||||
var c = new Float32x4Array(a.length);
|
||||
for (var i = 0; i < a.length; i++) {
|
||||
c[i] = SIMD.float32x4.add(a[i], b[i]);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
```
|
||||
|
||||
## 参考链接
|
||||
|
||||
- MDN, [SIMD](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SIMD)
|
||||
- TC39, [ECMAScript SIMD](https://github.com/tc39/ecmascript_simd)
|
||||
- Axel Rauschmayer, [JavaScript gains support for SIMD](http://www.2ality.com/2013/12/simd-js.html)
|
||||
|
@ -318,6 +318,13 @@ ES7推出了字符串补全长度的功能。如果某个字符串不够指定
|
||||
'xxx'.padEnd(2, 'ab') // 'xxx'
|
||||
```
|
||||
|
||||
如果用来补全的字符串与原字符串,两者的长度之和超过了制定的最小长度,则会截去超出位数的补全字符串。
|
||||
|
||||
```javascript
|
||||
'abc'.padStart(10, '0123456789')
|
||||
// '0123456abc'
|
||||
```
|
||||
|
||||
如果省略第二个参数,则会用空格补全长度。
|
||||
|
||||
```javascript
|
||||
|
Loading…
x
Reference in New Issue
Block a user