mirror of
https://github.com/ruanyf/es6tutorial.git
synced 2025-05-25 03:02:21 +00:00
commit
f1d954a41e
@ -28,7 +28,7 @@ function add(x, y) {
|
|||||||
return x + y;
|
return x + y;
|
||||||
}
|
}
|
||||||
|
|
||||||
var numbers = [4, 38];
|
const numbers = [4, 38];
|
||||||
add(...numbers) // 42
|
add(...numbers) // 42
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -38,7 +38,7 @@ add(...numbers) // 42
|
|||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
function f(v, w, x, y, z) { }
|
function f(v, w, x, y, z) { }
|
||||||
var args = [0, 1];
|
const args = [0, 1];
|
||||||
f(-1, ...args, 2, ...[3]);
|
f(-1, ...args, 2, ...[3]);
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -74,7 +74,7 @@ f.apply(null, args);
|
|||||||
function f(x, y, z) {
|
function f(x, y, z) {
|
||||||
// ...
|
// ...
|
||||||
}
|
}
|
||||||
var args = [0, 1, 2];
|
let args = [0, 1, 2];
|
||||||
f(...args);
|
f(...args);
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -102,8 +102,8 @@ var arr2 = [3, 4, 5];
|
|||||||
Array.prototype.push.apply(arr1, arr2);
|
Array.prototype.push.apply(arr1, arr2);
|
||||||
|
|
||||||
// ES6 的写法
|
// ES6 的写法
|
||||||
var arr1 = [0, 1, 2];
|
let arr1 = [0, 1, 2];
|
||||||
var arr2 = [3, 4, 5];
|
let arr2 = [3, 4, 5];
|
||||||
arr1.push(...arr2);
|
arr1.push(...arr2);
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -185,8 +185,8 @@ const [first, ...middle, last] = [1, 2, 3, 4, 5];
|
|||||||
JavaScript 的函数只能返回一个值,如果需要返回多个值,只能返回数组或对象。扩展运算符提供了解决这个问题的一种变通方法。
|
JavaScript 的函数只能返回一个值,如果需要返回多个值,只能返回数组或对象。扩展运算符提供了解决这个问题的一种变通方法。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var dateFields = readDateFields(database);
|
let dateFields = readDateFields(database);
|
||||||
var d = new Date(...dateFields);
|
let d = new Date(...dateFields);
|
||||||
```
|
```
|
||||||
|
|
||||||
上面代码从数据库取出一行数据,通过扩展运算符,直接将其传入构造函数`Date`。
|
上面代码从数据库取出一行数据,通过扩展运算符,直接将其传入构造函数`Date`。
|
||||||
@ -236,8 +236,8 @@ str.split('').reverse().join('')
|
|||||||
任何 Iterator 接口的对象(参阅 Iterator 一章),都可以用扩展运算符转为真正的数组。
|
任何 Iterator 接口的对象(参阅 Iterator 一章),都可以用扩展运算符转为真正的数组。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var nodeList = document.querySelectorAll('div');
|
let nodeList = document.querySelectorAll('div');
|
||||||
var array = [...nodeList];
|
let array = [...nodeList];
|
||||||
```
|
```
|
||||||
|
|
||||||
上面代码中,`querySelectorAll`方法返回的是一个`nodeList`对象。它不是数组,而是一个类似数组的对象。这时,扩展运算符可以将其转为真正的数组,原因就在于`NodeList`对象实现了 Iterator 。
|
上面代码中,`querySelectorAll`方法返回的是一个`nodeList`对象。它不是数组,而是一个类似数组的对象。这时,扩展运算符可以将其转为真正的数组,原因就在于`NodeList`对象实现了 Iterator 。
|
||||||
@ -275,7 +275,7 @@ let arr = [...map.keys()]; // [1, 2, 3]
|
|||||||
Generator 函数运行后,返回一个遍历器对象,因此也可以使用扩展运算符。
|
Generator 函数运行后,返回一个遍历器对象,因此也可以使用扩展运算符。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var go = function*(){
|
const go = function*(){
|
||||||
yield 1;
|
yield 1;
|
||||||
yield 2;
|
yield 2;
|
||||||
yield 3;
|
yield 3;
|
||||||
@ -289,7 +289,7 @@ var go = function*(){
|
|||||||
如果对没有 Iterator 接口的对象,使用扩展运算符,将会报错。
|
如果对没有 Iterator 接口的对象,使用扩展运算符,将会报错。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var obj = {a: 1, b: 2};
|
const obj = {a: 1, b: 2};
|
||||||
let arr = [...obj]; // TypeError: Cannot spread non-iterable object
|
let arr = [...obj]; // TypeError: Cannot spread non-iterable object
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -356,7 +356,7 @@ Array.from([1, 2, 3])
|
|||||||
```javascript
|
```javascript
|
||||||
// arguments对象
|
// arguments对象
|
||||||
function foo() {
|
function foo() {
|
||||||
var args = [...arguments];
|
const args = [...arguments];
|
||||||
}
|
}
|
||||||
|
|
||||||
// NodeList对象
|
// NodeList对象
|
||||||
@ -517,7 +517,7 @@ Array.prototype.copyWithin(target, start = 0, end = this.length)
|
|||||||
// {0: 1, 3: 1, length: 5}
|
// {0: 1, 3: 1, length: 5}
|
||||||
|
|
||||||
// 将2号位到数组结束,复制到0号位
|
// 将2号位到数组结束,复制到0号位
|
||||||
var i32a = new Int32Array([1, 2, 3, 4, 5]);
|
let i32a = new Int32Array([1, 2, 3, 4, 5]);
|
||||||
i32a.copyWithin(0, 2);
|
i32a.copyWithin(0, 2);
|
||||||
// Int32Array [3, 4, 5, 4, 5]
|
// Int32Array [3, 4, 5, 4, 5]
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ Float64|8|64位浮点数|double
|
|||||||
`ArrayBuffer`也是一个构造函数,可以分配一段可以存放数据的连续内存区域。
|
`ArrayBuffer`也是一个构造函数,可以分配一段可以存放数据的连续内存区域。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var buf = new ArrayBuffer(32);
|
const buf = new ArrayBuffer(32);
|
||||||
```
|
```
|
||||||
|
|
||||||
上面代码生成了一段32字节的内存区域,每个字节的值默认都是0。可以看到,`ArrayBuffer`构造函数的参数是所需要的内存大小(单位字节)。
|
上面代码生成了一段32字节的内存区域,每个字节的值默认都是0。可以看到,`ArrayBuffer`构造函数的参数是所需要的内存大小(单位字节)。
|
||||||
@ -57,8 +57,8 @@ var buf = new ArrayBuffer(32);
|
|||||||
为了读写这段内容,需要为它指定视图。`DataView`视图的创建,需要提供`ArrayBuffer`对象实例作为参数。
|
为了读写这段内容,需要为它指定视图。`DataView`视图的创建,需要提供`ArrayBuffer`对象实例作为参数。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var buf = new ArrayBuffer(32);
|
const buf = new ArrayBuffer(32);
|
||||||
var dataView = new DataView(buf);
|
const dataView = new DataView(buf);
|
||||||
dataView.getUint8(0) // 0
|
dataView.getUint8(0) // 0
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -67,11 +67,11 @@ dataView.getUint8(0) // 0
|
|||||||
另一种TypedArray视图,与`DataView`视图的一个区别是,它不是一个构造函数,而是一组构造函数,代表不同的数据格式。
|
另一种TypedArray视图,与`DataView`视图的一个区别是,它不是一个构造函数,而是一组构造函数,代表不同的数据格式。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var buffer = new ArrayBuffer(12);
|
const buffer = new ArrayBuffer(12);
|
||||||
|
|
||||||
var x1 = new Int32Array(buffer);
|
const x1 = new Int32Array(buffer);
|
||||||
x1[0] = 1;
|
x1[0] = 1;
|
||||||
var x2 = new Uint8Array(buffer);
|
const x2 = new Uint8Array(buffer);
|
||||||
x2[0] = 2;
|
x2[0] = 2;
|
||||||
|
|
||||||
x1[0] // 2
|
x1[0] // 2
|
||||||
@ -82,7 +82,7 @@ x1[0] // 2
|
|||||||
TypedArray视图的构造函数,除了接受`ArrayBuffer`实例作为参数,还可以接受普通数组作为参数,直接分配内存生成底层的`ArrayBuffer`实例,并同时完成对这段内存的赋值。
|
TypedArray视图的构造函数,除了接受`ArrayBuffer`实例作为参数,还可以接受普通数组作为参数,直接分配内存生成底层的`ArrayBuffer`实例,并同时完成对这段内存的赋值。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var typedArray = new Uint8Array([0,1,2]);
|
const typedArray = new Uint8Array([0,1,2]);
|
||||||
typedArray.length // 3
|
typedArray.length // 3
|
||||||
|
|
||||||
typedArray[0] = 5;
|
typedArray[0] = 5;
|
||||||
@ -96,7 +96,7 @@ typedArray // [5, 1, 2]
|
|||||||
`ArrayBuffer`实例的`byteLength`属性,返回所分配的内存区域的字节长度。
|
`ArrayBuffer`实例的`byteLength`属性,返回所分配的内存区域的字节长度。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var buffer = new ArrayBuffer(32);
|
const buffer = new ArrayBuffer(32);
|
||||||
buffer.byteLength
|
buffer.byteLength
|
||||||
// 32
|
// 32
|
||||||
```
|
```
|
||||||
@ -116,8 +116,8 @@ if (buffer.byteLength === n) {
|
|||||||
`ArrayBuffer`实例有一个`slice`方法,允许将内存区域的一部分,拷贝生成一个新的`ArrayBuffer`对象。
|
`ArrayBuffer`实例有一个`slice`方法,允许将内存区域的一部分,拷贝生成一个新的`ArrayBuffer`对象。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var buffer = new ArrayBuffer(8);
|
const buffer = new ArrayBuffer(8);
|
||||||
var newBuffer = buffer.slice(0, 3);
|
const newBuffer = buffer.slice(0, 3);
|
||||||
```
|
```
|
||||||
|
|
||||||
上面代码拷贝`buffer`对象的前3个字节(从0开始,到第3个字节前面结束),生成一个新的`ArrayBuffer`对象。`slice`方法其实包含两步,第一步是先分配一段新内存,第二步是将原来那个`ArrayBuffer`对象拷贝过去。
|
上面代码拷贝`buffer`对象的前3个字节(从0开始,到第3个字节前面结束),生成一个新的`ArrayBuffer`对象。`slice`方法其实包含两步,第一步是先分配一段新内存,第二步是将原来那个`ArrayBuffer`对象拷贝过去。
|
||||||
@ -131,10 +131,10 @@ var newBuffer = buffer.slice(0, 3);
|
|||||||
`ArrayBuffer`有一个静态方法`isView`,返回一个布尔值,表示参数是否为`ArrayBuffer`的视图实例。这个方法大致相当于判断参数,是否为TypedArray实例或`DataView`实例。
|
`ArrayBuffer`有一个静态方法`isView`,返回一个布尔值,表示参数是否为`ArrayBuffer`的视图实例。这个方法大致相当于判断参数,是否为TypedArray实例或`DataView`实例。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var buffer = new ArrayBuffer(8);
|
const buffer = new ArrayBuffer(8);
|
||||||
ArrayBuffer.isView(buffer) // false
|
ArrayBuffer.isView(buffer) // false
|
||||||
|
|
||||||
var v = new Int32Array(buffer);
|
const v = new Int32Array(buffer);
|
||||||
ArrayBuffer.isView(v) // true
|
ArrayBuffer.isView(v) // true
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -175,16 +175,16 @@ TypedArray数组提供9种构造函数,用来生成相应类型的数组实例
|
|||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
// 创建一个8字节的ArrayBuffer
|
// 创建一个8字节的ArrayBuffer
|
||||||
var b = new ArrayBuffer(8);
|
const b = new ArrayBuffer(8);
|
||||||
|
|
||||||
// 创建一个指向b的Int32视图,开始于字节0,直到缓冲区的末尾
|
// 创建一个指向b的Int32视图,开始于字节0,直到缓冲区的末尾
|
||||||
var v1 = new Int32Array(b);
|
const v1 = new Int32Array(b);
|
||||||
|
|
||||||
// 创建一个指向b的Uint8视图,开始于字节2,直到缓冲区的末尾
|
// 创建一个指向b的Uint8视图,开始于字节2,直到缓冲区的末尾
|
||||||
var v2 = new Uint8Array(b, 2);
|
const v2 = new Uint8Array(b, 2);
|
||||||
|
|
||||||
// 创建一个指向b的Int16视图,开始于字节2,长度为2
|
// 创建一个指向b的Int16视图,开始于字节2,长度为2
|
||||||
var v3 = new Int16Array(b, 2, 2);
|
const v3 = new Int16Array(b, 2, 2);
|
||||||
```
|
```
|
||||||
|
|
||||||
上面代码在一段长度为8个字节的内存(`b`)之上,生成了三个视图:`v1`、`v2`和`v3`。
|
上面代码在一段长度为8个字节的内存(`b`)之上,生成了三个视图:`v1`、`v2`和`v3`。
|
||||||
@ -200,8 +200,8 @@ var v3 = new Int16Array(b, 2, 2);
|
|||||||
注意,`byteOffset`必须与所要建立的数据类型一致,否则会报错。
|
注意,`byteOffset`必须与所要建立的数据类型一致,否则会报错。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var buffer = new ArrayBuffer(8);
|
const buffer = new ArrayBuffer(8);
|
||||||
var i16 = new Int16Array(buffer, 1);
|
const i16 = new Int16Array(buffer, 1);
|
||||||
// Uncaught RangeError: start offset of Int16Array should be a multiple of 2
|
// Uncaught RangeError: start offset of Int16Array should be a multiple of 2
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -214,7 +214,7 @@ var i16 = new Int16Array(buffer, 1);
|
|||||||
视图还可以不通过`ArrayBuffer`对象,直接分配内存而生成。
|
视图还可以不通过`ArrayBuffer`对象,直接分配内存而生成。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var f64a = new Float64Array(8);
|
const f64a = new Float64Array(8);
|
||||||
f64a[0] = 10;
|
f64a[0] = 10;
|
||||||
f64a[1] = 20;
|
f64a[1] = 20;
|
||||||
f64a[2] = f64a[0] + f64a[1];
|
f64a[2] = f64a[0] + f64a[1];
|
||||||
@ -227,7 +227,7 @@ f64a[2] = f64a[0] + f64a[1];
|
|||||||
TypedArray数组的构造函数,可以接受另一个TypedArray实例作为参数。
|
TypedArray数组的构造函数,可以接受另一个TypedArray实例作为参数。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var typedArray = new Int8Array(new Uint8Array(4));
|
const typedArray = new Int8Array(new Uint8Array(4));
|
||||||
```
|
```
|
||||||
|
|
||||||
上面代码中,`Int8Array`构造函数接受一个`Uint8Array`实例作为参数。
|
上面代码中,`Int8Array`构造函数接受一个`Uint8Array`实例作为参数。
|
||||||
@ -235,8 +235,8 @@ var typedArray = new Int8Array(new Uint8Array(4));
|
|||||||
注意,此时生成的新数组,只是复制了参数数组的值,对应的底层内存是不一样的。新数组会开辟一段新的内存储存数据,不会在原数组的内存之上建立视图。
|
注意,此时生成的新数组,只是复制了参数数组的值,对应的底层内存是不一样的。新数组会开辟一段新的内存储存数据,不会在原数组的内存之上建立视图。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var x = new Int8Array([1, 1]);
|
const x = new Int8Array([1, 1]);
|
||||||
var y = new Int8Array(x);
|
const y = new Int8Array(x);
|
||||||
x[0] // 1
|
x[0] // 1
|
||||||
y[0] // 1
|
y[0] // 1
|
||||||
|
|
||||||
@ -249,8 +249,8 @@ y[0] // 1
|
|||||||
如果想基于同一段内存,构造不同的视图,可以采用下面的写法。
|
如果想基于同一段内存,构造不同的视图,可以采用下面的写法。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var x = new Int8Array([1, 1]);
|
const x = new Int8Array([1, 1]);
|
||||||
var y = new Int8Array(x.buffer);
|
const y = new Int8Array(x.buffer);
|
||||||
x[0] // 1
|
x[0] // 1
|
||||||
y[0] // 1
|
y[0] // 1
|
||||||
|
|
||||||
@ -263,7 +263,7 @@ y[0] // 2
|
|||||||
构造函数的参数也可以是一个普通数组,然后直接生成TypedArray实例。
|
构造函数的参数也可以是一个普通数组,然后直接生成TypedArray实例。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var typedArray = new Uint8Array([1, 2, 3, 4]);
|
const typedArray = new Uint8Array([1, 2, 3, 4]);
|
||||||
```
|
```
|
||||||
|
|
||||||
注意,这时TypedArray视图会重新开辟内存,不会在原数组的内存上建立视图。
|
注意,这时TypedArray视图会重新开辟内存,不会在原数组的内存上建立视图。
|
||||||
@ -273,7 +273,7 @@ var typedArray = new Uint8Array([1, 2, 3, 4]);
|
|||||||
TypedArray数组也可以转换回普通数组。
|
TypedArray数组也可以转换回普通数组。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var normalArray = Array.prototype.slice.call(typedArray);
|
const normalArray = Array.prototype.slice.call(typedArray);
|
||||||
```
|
```
|
||||||
|
|
||||||
### 数组方法
|
### 数组方法
|
||||||
@ -343,10 +343,10 @@ for (let byte of ui8) {
|
|||||||
字节序指的是数值在内存中的表示方式。
|
字节序指的是数值在内存中的表示方式。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var buffer = new ArrayBuffer(16);
|
const buffer = new ArrayBuffer(16);
|
||||||
var int32View = new Int32Array(buffer);
|
const int32View = new Int32Array(buffer);
|
||||||
|
|
||||||
for (var i = 0; i < int32View.length; i++) {
|
for (let i = 0; i < int32View.length; i++) {
|
||||||
int32View[i] = i * 2;
|
int32View[i] = i * 2;
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -356,9 +356,9 @@ for (var i = 0; i < int32View.length; i++) {
|
|||||||
如果在这段数据上接着建立一个16位整数的视图,则可以读出完全不一样的结果。
|
如果在这段数据上接着建立一个16位整数的视图,则可以读出完全不一样的结果。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var int16View = new Int16Array(buffer);
|
const int16View = new Int16Array(buffer);
|
||||||
|
|
||||||
for (var i = 0; i < int16View.length; i++) {
|
for (let i = 0; i < int16View.length; i++) {
|
||||||
console.log("Entry " + i + ": " + int16View[i]);
|
console.log("Entry " + i + ": " + int16View[i]);
|
||||||
}
|
}
|
||||||
// Entry 0: 0
|
// Entry 0: 0
|
||||||
@ -381,14 +381,14 @@ for (var i = 0; i < int16View.length; i++) {
|
|||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
// 假定某段buffer包含如下字节 [0x02, 0x01, 0x03, 0x07]
|
// 假定某段buffer包含如下字节 [0x02, 0x01, 0x03, 0x07]
|
||||||
var buffer = new ArrayBuffer(4);
|
const buffer = new ArrayBuffer(4);
|
||||||
var v1 = new Uint8Array(buffer);
|
const v1 = new Uint8Array(buffer);
|
||||||
v1[0] = 2;
|
v1[0] = 2;
|
||||||
v1[1] = 1;
|
v1[1] = 1;
|
||||||
v1[2] = 3;
|
v1[2] = 3;
|
||||||
v1[3] = 7;
|
v1[3] = 7;
|
||||||
|
|
||||||
var uInt16View = new Uint16Array(buffer);
|
const uInt16View = new Uint16Array(buffer);
|
||||||
|
|
||||||
// 计算机采用小端字节序
|
// 计算机采用小端字节序
|
||||||
// 所以头两个字节等于258
|
// 所以头两个字节等于258
|
||||||
@ -453,9 +453,9 @@ function ab2str(buf) {
|
|||||||
|
|
||||||
// 字符串转为ArrayBuffer对象,参数为字符串
|
// 字符串转为ArrayBuffer对象,参数为字符串
|
||||||
function str2ab(str) {
|
function str2ab(str) {
|
||||||
var buf = new ArrayBuffer(str.length * 2); // 每个字符占用2个字节
|
const buf = new ArrayBuffer(str.length * 2); // 每个字符占用2个字节
|
||||||
var bufView = new Uint16Array(buf);
|
const bufView = new Uint16Array(buf);
|
||||||
for (var i = 0, strLen = str.length; i < strLen; i++) {
|
for (let i = 0, strLen = str.length; i < strLen; i++) {
|
||||||
bufView[i] = str.charCodeAt(i);
|
bufView[i] = str.charCodeAt(i);
|
||||||
}
|
}
|
||||||
return buf;
|
return buf;
|
||||||
@ -469,7 +469,7 @@ function str2ab(str) {
|
|||||||
TypedArray数组的溢出处理规则,简单来说,就是抛弃溢出的位,然后按照视图类型进行解释。
|
TypedArray数组的溢出处理规则,简单来说,就是抛弃溢出的位,然后按照视图类型进行解释。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var uint8 = new Uint8Array(1);
|
const uint8 = new Uint8Array(1);
|
||||||
|
|
||||||
uint8[0] = 256;
|
uint8[0] = 256;
|
||||||
uint8[0] // 0
|
uint8[0] // 0
|
||||||
@ -499,7 +499,7 @@ uint8[0] // 255
|
|||||||
请看下面的例子。
|
请看下面的例子。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var int8 = new Int8Array(1);
|
const int8 = new Int8Array(1);
|
||||||
|
|
||||||
int8[0] = 128;
|
int8[0] = 128;
|
||||||
int8[0] // -128
|
int8[0] // -128
|
||||||
@ -513,7 +513,7 @@ int8[0] // 127
|
|||||||
`Uint8ClampedArray`视图的溢出规则,与上面的规则不同。它规定,凡是发生正向溢出,该值一律等于当前数据类型的最大值,即255;如果发生负向溢出,该值一律等于当前数据类型的最小值,即0。
|
`Uint8ClampedArray`视图的溢出规则,与上面的规则不同。它规定,凡是发生正向溢出,该值一律等于当前数据类型的最大值,即255;如果发生负向溢出,该值一律等于当前数据类型的最小值,即0。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var uint8c = new Uint8ClampedArray(1);
|
const uint8c = new Uint8ClampedArray(1);
|
||||||
|
|
||||||
uint8c[0] = 256;
|
uint8c[0] = 256;
|
||||||
uint8c[0] // 255
|
uint8c[0] // 255
|
||||||
@ -529,8 +529,8 @@ uint8c[0] // 0
|
|||||||
TypedArray实例的`buffer`属性,返回整段内存区域对应的`ArrayBuffer`对象。该属性为只读属性。
|
TypedArray实例的`buffer`属性,返回整段内存区域对应的`ArrayBuffer`对象。该属性为只读属性。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var a = new Float32Array(64);
|
const a = new Float32Array(64);
|
||||||
var b = new Uint8Array(a.buffer);
|
const b = new Uint8Array(a.buffer);
|
||||||
```
|
```
|
||||||
|
|
||||||
上面代码的`a`视图对象和`b`视图对象,对应同一个`ArrayBuffer`对象,即同一段内存。
|
上面代码的`a`视图对象和`b`视图对象,对应同一个`ArrayBuffer`对象,即同一段内存。
|
||||||
@ -540,11 +540,11 @@ var b = new Uint8Array(a.buffer);
|
|||||||
`byteLength`属性返回TypedArray数组占据的内存长度,单位为字节。`byteOffset`属性返回TypedArray数组从底层`ArrayBuffer`对象的哪个字节开始。这两个属性都是只读属性。
|
`byteLength`属性返回TypedArray数组占据的内存长度,单位为字节。`byteOffset`属性返回TypedArray数组从底层`ArrayBuffer`对象的哪个字节开始。这两个属性都是只读属性。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var b = new ArrayBuffer(8);
|
const b = new ArrayBuffer(8);
|
||||||
|
|
||||||
var v1 = new Int32Array(b);
|
const v1 = new Int32Array(b);
|
||||||
var v2 = new Uint8Array(b, 2);
|
const v2 = new Uint8Array(b, 2);
|
||||||
var v3 = new Int16Array(b, 2, 2);
|
const v3 = new Int16Array(b, 2, 2);
|
||||||
|
|
||||||
v1.byteLength // 8
|
v1.byteLength // 8
|
||||||
v2.byteLength // 6
|
v2.byteLength // 6
|
||||||
@ -560,7 +560,7 @@ v3.byteOffset // 2
|
|||||||
`length`属性表示TypedArray数组含有多少个成员。注意将`byteLength`属性和`length`属性区分,前者是字节长度,后者是成员长度。
|
`length`属性表示TypedArray数组含有多少个成员。注意将`byteLength`属性和`length`属性区分,前者是字节长度,后者是成员长度。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var a = new Int16Array(8);
|
const a = new Int16Array(8);
|
||||||
|
|
||||||
a.length // 8
|
a.length // 8
|
||||||
a.byteLength // 16
|
a.byteLength // 16
|
||||||
@ -571,8 +571,8 @@ a.byteLength // 16
|
|||||||
TypedArray数组的`set`方法用于复制数组(普通数组或TypedArray数组),也就是将一段内容完全复制到另一段内存。
|
TypedArray数组的`set`方法用于复制数组(普通数组或TypedArray数组),也就是将一段内容完全复制到另一段内存。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var a = new Uint8Array(8);
|
const a = new Uint8Array(8);
|
||||||
var b = new Uint8Array(8);
|
const b = new Uint8Array(8);
|
||||||
|
|
||||||
b.set(a);
|
b.set(a);
|
||||||
```
|
```
|
||||||
@ -582,8 +582,8 @@ b.set(a);
|
|||||||
`set`方法还可以接受第二个参数,表示从`b`对象的哪一个成员开始复制`a`对象。
|
`set`方法还可以接受第二个参数,表示从`b`对象的哪一个成员开始复制`a`对象。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var a = new Uint16Array(8);
|
const a = new Uint16Array(8);
|
||||||
var b = new Uint16Array(10);
|
const b = new Uint16Array(10);
|
||||||
|
|
||||||
b.set(a, 2)
|
b.set(a, 2)
|
||||||
```
|
```
|
||||||
@ -595,8 +595,8 @@ b.set(a, 2)
|
|||||||
`subarray`方法是对于TypedArray数组的一部分,再建立一个新的视图。
|
`subarray`方法是对于TypedArray数组的一部分,再建立一个新的视图。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var a = new Uint16Array(8);
|
const a = new Uint16Array(8);
|
||||||
var b = a.subarray(2,3);
|
const b = a.subarray(2,3);
|
||||||
|
|
||||||
a.byteLength // 16
|
a.byteLength // 16
|
||||||
b.byteLength // 2
|
b.byteLength // 2
|
||||||
@ -655,7 +655,7 @@ Uint16Array.from([0, 1, 2])
|
|||||||
这个方法还可以将一种TypedArray实例,转为另一种。
|
这个方法还可以将一种TypedArray实例,转为另一种。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var ui16 = Uint16Array.from(Uint8Array.of(0, 1, 2));
|
const ui16 = Uint16Array.from(Uint8Array.of(0, 1, 2));
|
||||||
ui16 instanceof Uint16Array // true
|
ui16 instanceof Uint16Array // true
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -676,11 +676,11 @@ Int16Array.from(Int8Array.of(127, 126, 125), x => 2 * x)
|
|||||||
由于视图的构造函数可以指定起始位置和长度,所以在同一段内存之中,可以依次存放不同类型的数据,这叫做“复合视图”。
|
由于视图的构造函数可以指定起始位置和长度,所以在同一段内存之中,可以依次存放不同类型的数据,这叫做“复合视图”。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var buffer = new ArrayBuffer(24);
|
const buffer = new ArrayBuffer(24);
|
||||||
|
|
||||||
var idView = new Uint32Array(buffer, 0, 1);
|
const idView = new Uint32Array(buffer, 0, 1);
|
||||||
var usernameView = new Uint8Array(buffer, 4, 16);
|
const usernameView = new Uint8Array(buffer, 4, 16);
|
||||||
var amountDueView = new Float32Array(buffer, 20, 1);
|
const amountDueView = new Float32Array(buffer, 20, 1);
|
||||||
```
|
```
|
||||||
|
|
||||||
上面代码将一个24字节长度的`ArrayBuffer`对象,分成三个部分:
|
上面代码将一个24字节长度的`ArrayBuffer`对象,分成三个部分:
|
||||||
@ -714,8 +714,8 @@ DataView(ArrayBuffer buffer [, 字节起始位置 [, 长度]]);
|
|||||||
下面是一个例子。
|
下面是一个例子。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var buffer = new ArrayBuffer(24);
|
const buffer = new ArrayBuffer(24);
|
||||||
var dv = new DataView(buffer);
|
const dv = new DataView(buffer);
|
||||||
```
|
```
|
||||||
|
|
||||||
`DataView`实例有以下属性,含义与TypedArray实例的同名方法相同。
|
`DataView`实例有以下属性,含义与TypedArray实例的同名方法相同。
|
||||||
@ -738,17 +738,17 @@ var dv = new DataView(buffer);
|
|||||||
这一系列`get`方法的参数都是一个字节序号(不能是负数,否则会报错),表示从哪个字节开始读取。
|
这一系列`get`方法的参数都是一个字节序号(不能是负数,否则会报错),表示从哪个字节开始读取。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var buffer = new ArrayBuffer(24);
|
const buffer = new ArrayBuffer(24);
|
||||||
var dv = new DataView(buffer);
|
const dv = new DataView(buffer);
|
||||||
|
|
||||||
// 从第1个字节读取一个8位无符号整数
|
// 从第1个字节读取一个8位无符号整数
|
||||||
var v1 = dv.getUint8(0);
|
const v1 = dv.getUint8(0);
|
||||||
|
|
||||||
// 从第2个字节读取一个16位无符号整数
|
// 从第2个字节读取一个16位无符号整数
|
||||||
var v2 = dv.getUint16(1);
|
const v2 = dv.getUint16(1);
|
||||||
|
|
||||||
// 从第4个字节读取一个16位无符号整数
|
// 从第4个字节读取一个16位无符号整数
|
||||||
var v3 = dv.getUint16(3);
|
const v3 = dv.getUint16(3);
|
||||||
```
|
```
|
||||||
|
|
||||||
上面代码读取了`ArrayBuffer`对象的前5个字节,其中有一个8位整数和两个十六位整数。
|
上面代码读取了`ArrayBuffer`对象的前5个字节,其中有一个8位整数和两个十六位整数。
|
||||||
@ -757,13 +757,13 @@ var v3 = dv.getUint16(3);
|
|||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
// 小端字节序
|
// 小端字节序
|
||||||
var v1 = dv.getUint16(1, true);
|
const v1 = dv.getUint16(1, true);
|
||||||
|
|
||||||
// 大端字节序
|
// 大端字节序
|
||||||
var v2 = dv.getUint16(3, false);
|
const v2 = dv.getUint16(3, false);
|
||||||
|
|
||||||
// 大端字节序
|
// 大端字节序
|
||||||
var v3 = dv.getUint16(3);
|
const v3 = dv.getUint16(3);
|
||||||
```
|
```
|
||||||
|
|
||||||
DataView视图提供8个方法写入内存。
|
DataView视图提供8个方法写入内存。
|
||||||
@ -793,8 +793,8 @@ dv.setFloat32(8, 2.5, true);
|
|||||||
如果不确定正在使用的计算机的字节序,可以采用下面的判断方式。
|
如果不确定正在使用的计算机的字节序,可以采用下面的判断方式。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var littleEndian = (function() {
|
const littleEndian = (function() {
|
||||||
var buffer = new ArrayBuffer(2);
|
const buffer = new ArrayBuffer(2);
|
||||||
new DataView(buffer).setInt16(0, 256, true);
|
new DataView(buffer).setInt16(0, 256, true);
|
||||||
return new Int16Array(buffer)[0] === 256;
|
return new Int16Array(buffer)[0] === 256;
|
||||||
})();
|
})();
|
||||||
@ -811,7 +811,7 @@ var littleEndian = (function() {
|
|||||||
传统上,服务器通过AJAX操作只能返回文本数据,即`responseType`属性默认为`text`。`XMLHttpRequest`第二版`XHR2`允许服务器返回二进制数据,这时分成两种情况。如果明确知道返回的二进制数据类型,可以把返回类型(`responseType`)设为`arraybuffer`;如果不知道,就设为`blob`。
|
传统上,服务器通过AJAX操作只能返回文本数据,即`responseType`属性默认为`text`。`XMLHttpRequest`第二版`XHR2`允许服务器返回二进制数据,这时分成两种情况。如果明确知道返回的二进制数据类型,可以把返回类型(`responseType`)设为`arraybuffer`;如果不知道,就设为`blob`。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var xhr = new XMLHttpRequest();
|
let xhr = new XMLHttpRequest();
|
||||||
xhr.open('GET', someUrl);
|
xhr.open('GET', someUrl);
|
||||||
xhr.responseType = 'arraybuffer';
|
xhr.responseType = 'arraybuffer';
|
||||||
|
|
||||||
@ -828,9 +828,9 @@ xhr.send();
|
|||||||
```javascript
|
```javascript
|
||||||
xhr.onreadystatechange = function () {
|
xhr.onreadystatechange = function () {
|
||||||
if (req.readyState === 4 ) {
|
if (req.readyState === 4 ) {
|
||||||
var arrayResponse = xhr.response;
|
const arrayResponse = xhr.response;
|
||||||
var dataView = new DataView(arrayResponse);
|
const dataView = new DataView(arrayResponse);
|
||||||
var ints = new Uint32Array(dataView.byteLength / 4);
|
const ints = new Uint32Array(dataView.byteLength / 4);
|
||||||
|
|
||||||
xhrDiv.style.backgroundColor = "#00FF00";
|
xhrDiv.style.backgroundColor = "#00FF00";
|
||||||
xhrDiv.innerText = "Array is " + ints.length + "uints long";
|
xhrDiv.innerText = "Array is " + ints.length + "uints long";
|
||||||
@ -843,11 +843,11 @@ xhr.onreadystatechange = function () {
|
|||||||
网页`Canvas`元素输出的二进制像素数据,就是TypedArray数组。
|
网页`Canvas`元素输出的二进制像素数据,就是TypedArray数组。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var canvas = document.getElementById('myCanvas');
|
const canvas = document.getElementById('myCanvas');
|
||||||
var ctx = canvas.getContext('2d');
|
const ctx = canvas.getContext('2d');
|
||||||
|
|
||||||
var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
||||||
var uint8ClampedArray = imageData.data;
|
const uint8ClampedArray = imageData.data;
|
||||||
```
|
```
|
||||||
|
|
||||||
需要注意的是,上面代码的`uint8ClampedArray`虽然是一个TypedArray数组,但是它的视图类型是一种针对`Canvas`元素的专有类型`Uint8ClampedArray`。这个视图类型的特点,就是专门针对颜色,把每个字节解读为无符号的8位整数,即只能取值0~255,而且发生运算的时候自动过滤高位溢出。这为图像处理带来了巨大的方便。
|
需要注意的是,上面代码的`uint8ClampedArray`虽然是一个TypedArray数组,但是它的视图类型是一种针对`Canvas`元素的专有类型`Uint8ClampedArray`。这个视图类型的特点,就是专门针对颜色,把每个字节解读为无符号的8位整数,即只能取值0~255,而且发生运算的时候自动过滤高位溢出。这为图像处理带来了巨大的方便。
|
||||||
@ -871,19 +871,19 @@ pixels[i] *= gamma;
|
|||||||
`WebSocket`可以通过`ArrayBuffer`,发送或接收二进制数据。
|
`WebSocket`可以通过`ArrayBuffer`,发送或接收二进制数据。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var socket = new WebSocket('ws://127.0.0.1:8081');
|
let socket = new WebSocket('ws://127.0.0.1:8081');
|
||||||
socket.binaryType = 'arraybuffer';
|
socket.binaryType = 'arraybuffer';
|
||||||
|
|
||||||
// Wait until socket is open
|
// Wait until socket is open
|
||||||
socket.addEventListener('open', function (event) {
|
socket.addEventListener('open', function (event) {
|
||||||
// Send binary data
|
// Send binary data
|
||||||
var typedArray = new Uint8Array(4);
|
const typedArray = new Uint8Array(4);
|
||||||
socket.send(typedArray.buffer);
|
socket.send(typedArray.buffer);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Receive binary data
|
// Receive binary data
|
||||||
socket.addEventListener('message', function (event) {
|
socket.addEventListener('message', function (event) {
|
||||||
var arrayBuffer = event.data;
|
const arrayBuffer = event.data;
|
||||||
// ···
|
// ···
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
@ -907,12 +907,12 @@ fetch(url)
|
|||||||
如果知道一个文件的二进制数据类型,也可以将这个文件读取为`ArrayBuffer`对象。
|
如果知道一个文件的二进制数据类型,也可以将这个文件读取为`ArrayBuffer`对象。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var fileInput = document.getElementById('fileInput');
|
const fileInput = document.getElementById('fileInput');
|
||||||
var file = fileInput.files[0];
|
const file = fileInput.files[0];
|
||||||
var reader = new FileReader();
|
const reader = new FileReader();
|
||||||
reader.readAsArrayBuffer(file);
|
reader.readAsArrayBuffer(file);
|
||||||
reader.onload = function () {
|
reader.onload = function () {
|
||||||
var arrayBuffer = reader.result;
|
const arrayBuffer = reader.result;
|
||||||
// ···
|
// ···
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
@ -920,7 +920,7 @@ reader.onload = function () {
|
|||||||
下面以处理bmp文件为例。假定`file`变量是一个指向bmp文件的文件对象,首先读取文件。
|
下面以处理bmp文件为例。假定`file`变量是一个指向bmp文件的文件对象,首先读取文件。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var reader = new FileReader();
|
const reader = new FileReader();
|
||||||
reader.addEventListener("load", processimage, false);
|
reader.addEventListener("load", processimage, false);
|
||||||
reader.readAsArrayBuffer(file);
|
reader.readAsArrayBuffer(file);
|
||||||
```
|
```
|
||||||
@ -929,9 +929,9 @@ reader.readAsArrayBuffer(file);
|
|||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
function processimage(e) {
|
function processimage(e) {
|
||||||
var buffer = e.target.result;
|
const buffer = e.target.result;
|
||||||
var datav = new DataView(buffer);
|
const datav = new DataView(buffer);
|
||||||
var bitmap = {};
|
const bitmap = {};
|
||||||
// 具体的处理步骤
|
// 具体的处理步骤
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -967,7 +967,7 @@ bitmap.infoheader.biClrImportant = datav.getUint32(50, true);
|
|||||||
最后处理图像本身的像素信息。
|
最后处理图像本身的像素信息。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var start = bitmap.fileheader.bfOffBits;
|
const start = bitmap.fileheader.bfOffBits;
|
||||||
bitmap.pixels = new Uint8Array(buffer, start);
|
bitmap.pixels = new Uint8Array(buffer, start);
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -979,7 +979,7 @@ JavaScript 是单线程的,Web worker 引入了多线程:主线程用来与
|
|||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
// 主线程
|
// 主线程
|
||||||
var w = new Worker('myworker.js');
|
const w = new Worker('myworker.js');
|
||||||
```
|
```
|
||||||
|
|
||||||
上面代码中,主线程新建了一个 Worker 线程。该线程与主线程之间会有一个通信渠道,主线程通过`w.postMessage`向 Worker 线程发消息,同时通过`message`事件监听 Worker 线程的回应。
|
上面代码中,主线程新建了一个 Worker 线程。该线程与主线程之间会有一个通信渠道,主线程通过`w.postMessage`向 Worker 线程发消息,同时通过`message`事件监听 Worker 线程的回应。
|
||||||
@ -1012,7 +1012,7 @@ ES2017 引入[`SharedArrayBuffer`](https://github.com/tc39/ecmascript_sharedmem/
|
|||||||
// 主线程
|
// 主线程
|
||||||
|
|
||||||
// 新建 1KB 共享内存
|
// 新建 1KB 共享内存
|
||||||
var sharedBuffer = new SharedArrayBuffer(1024);
|
const sharedBuffer = new SharedArrayBuffer(1024);
|
||||||
|
|
||||||
// 主线程将共享内存的地址发送出去
|
// 主线程将共享内存的地址发送出去
|
||||||
w.postMessage(sharedBuffer);
|
w.postMessage(sharedBuffer);
|
||||||
@ -1027,7 +1027,6 @@ Worker 线程从事件的`data`属性上面取到数据。
|
|||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
// Worker 线程
|
// Worker 线程
|
||||||
var sharedBuffer;
|
|
||||||
onmessage = function (ev) {
|
onmessage = function (ev) {
|
||||||
// 主线程共享的数据,就是 1KB 的共享内存
|
// 主线程共享的数据,就是 1KB 的共享内存
|
||||||
const sharedBuffer = ev.data;
|
const sharedBuffer = ev.data;
|
||||||
@ -1045,13 +1044,13 @@ onmessage = function (ev) {
|
|||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
// 分配 10 万个 32 位整数占据的内存空间
|
// 分配 10 万个 32 位整数占据的内存空间
|
||||||
var sab = new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 100000);
|
const sab = new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 100000);
|
||||||
|
|
||||||
// 建立 32 位整数视图
|
// 建立 32 位整数视图
|
||||||
var ia = new Int32Array(sab); // ia.length == 100000
|
const ia = new Int32Array(sab); // ia.length == 100000
|
||||||
|
|
||||||
// 新建一个质数生成器
|
// 新建一个质数生成器
|
||||||
var primes = new PrimeGenerator();
|
const primes = new PrimeGenerator();
|
||||||
|
|
||||||
// 将 10 万个质数,写入这段内存空间
|
// 将 10 万个质数,写入这段内存空间
|
||||||
for ( let i=0 ; i < ia.length ; i++ )
|
for ( let i=0 ; i < ia.length ; i++ )
|
||||||
@ -1065,7 +1064,7 @@ Worker 线程收到数据后的处理如下。
|
|||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
// Worker 线程
|
// Worker 线程
|
||||||
var ia;
|
let ia;
|
||||||
onmessage = function (ev) {
|
onmessage = function (ev) {
|
||||||
ia = ev.data;
|
ia = ev.data;
|
||||||
console.log(ia.length); // 100000
|
console.log(ia.length); // 100000
|
||||||
@ -1098,8 +1097,8 @@ console.log(ia[42]);
|
|||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
// 主线程
|
// 主线程
|
||||||
var sab = new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 100000);
|
const sab = new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT * 100000);
|
||||||
var ia = new Int32Array(sab);
|
const ia = new Int32Array(sab);
|
||||||
|
|
||||||
for (let i = 0; i < ia.length; i++) {
|
for (let i = 0; i < ia.length; i++) {
|
||||||
ia[i] = primes.next(); // 将质数放入 ia
|
ia[i] = primes.next(); // 将质数放入 ia
|
||||||
|
@ -9,9 +9,9 @@ async 函数是什么?一句话,它就是 Generator 函数的语法糖。
|
|||||||
前文有一个 Generator 函数,依次读取两个文件。
|
前文有一个 Generator 函数,依次读取两个文件。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var fs = require('fs');
|
const fs = require('fs');
|
||||||
|
|
||||||
var readFile = function (fileName) {
|
const readFile = function (fileName) {
|
||||||
return new Promise(function (resolve, reject) {
|
return new Promise(function (resolve, reject) {
|
||||||
fs.readFile(fileName, function(error, data) {
|
fs.readFile(fileName, function(error, data) {
|
||||||
if (error) return reject(error);
|
if (error) return reject(error);
|
||||||
@ -20,9 +20,9 @@ var readFile = function (fileName) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
var gen = function* () {
|
const gen = function* () {
|
||||||
var f1 = yield readFile('/etc/fstab');
|
const f1 = yield readFile('/etc/fstab');
|
||||||
var f2 = yield readFile('/etc/shells');
|
const f2 = yield readFile('/etc/shells');
|
||||||
console.log(f1.toString());
|
console.log(f1.toString());
|
||||||
console.log(f2.toString());
|
console.log(f2.toString());
|
||||||
};
|
};
|
||||||
@ -31,9 +31,9 @@ var gen = function* () {
|
|||||||
写成`async`函数,就是下面这样。
|
写成`async`函数,就是下面这样。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var asyncReadFile = async function () {
|
const asyncReadFile = async function () {
|
||||||
var f1 = await readFile('/etc/fstab');
|
const f1 = await readFile('/etc/fstab');
|
||||||
var f2 = await readFile('/etc/shells');
|
const f2 = await readFile('/etc/shells');
|
||||||
console.log(f1.toString());
|
console.log(f1.toString());
|
||||||
console.log(f2.toString());
|
console.log(f2.toString());
|
||||||
};
|
};
|
||||||
@ -75,8 +75,8 @@ asyncReadFile();
|
|||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
async function getStockPriceByName(name) {
|
async function getStockPriceByName(name) {
|
||||||
var symbol = await getStockSymbol(name);
|
const symbol = await getStockSymbol(name);
|
||||||
var stockPrice = await getStockPrice(symbol);
|
const stockPrice = await getStockPrice(symbol);
|
||||||
return stockPrice;
|
return stockPrice;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -318,9 +318,9 @@ async function f() {
|
|||||||
```javascript
|
```javascript
|
||||||
async function main() {
|
async function main() {
|
||||||
try {
|
try {
|
||||||
var val1 = await firstStep();
|
const val1 = await firstStep();
|
||||||
var val2 = await secondStep(val1);
|
const val2 = await secondStep(val1);
|
||||||
var val3 = await thirdStep(val1, val2);
|
const val3 = await thirdStep(val1, val2);
|
||||||
|
|
||||||
console.log('Final: ', val3);
|
console.log('Final: ', val3);
|
||||||
}
|
}
|
||||||
@ -503,10 +503,11 @@ function fn(args) {
|
|||||||
```javascript
|
```javascript
|
||||||
function spawn(genF) {
|
function spawn(genF) {
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
var gen = genF();
|
const gen = genF();
|
||||||
function step(nextF) {
|
function step(nextF) {
|
||||||
|
let next;
|
||||||
try {
|
try {
|
||||||
var next = nextF();
|
next = nextF();
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
return reject(e);
|
return reject(e);
|
||||||
}
|
}
|
||||||
@ -536,13 +537,13 @@ function spawn(genF) {
|
|||||||
function chainAnimationsPromise(elem, animations) {
|
function chainAnimationsPromise(elem, animations) {
|
||||||
|
|
||||||
// 变量ret用来保存上一个动画的返回值
|
// 变量ret用来保存上一个动画的返回值
|
||||||
var ret = null;
|
let ret = null;
|
||||||
|
|
||||||
// 新建一个空的Promise
|
// 新建一个空的Promise
|
||||||
var p = Promise.resolve();
|
let p = Promise.resolve();
|
||||||
|
|
||||||
// 使用then方法,添加所有动画
|
// 使用then方法,添加所有动画
|
||||||
for(var anim of animations) {
|
for(let anim of animations) {
|
||||||
p = p.then(function(val) {
|
p = p.then(function(val) {
|
||||||
ret = val;
|
ret = val;
|
||||||
return anim(elem);
|
return anim(elem);
|
||||||
@ -567,9 +568,9 @@ function chainAnimationsPromise(elem, animations) {
|
|||||||
function chainAnimationsGenerator(elem, animations) {
|
function chainAnimationsGenerator(elem, animations) {
|
||||||
|
|
||||||
return spawn(function*() {
|
return spawn(function*() {
|
||||||
var ret = null;
|
let ret = null;
|
||||||
try {
|
try {
|
||||||
for(var anim of animations) {
|
for(let anim of animations) {
|
||||||
ret = yield anim(elem);
|
ret = yield anim(elem);
|
||||||
}
|
}
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
@ -587,9 +588,9 @@ function chainAnimationsGenerator(elem, animations) {
|
|||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
async function chainAnimationsAsync(elem, animations) {
|
async function chainAnimationsAsync(elem, animations) {
|
||||||
var ret = null;
|
let ret = null;
|
||||||
try {
|
try {
|
||||||
for(var anim of animations) {
|
for(let anim of animations) {
|
||||||
ret = await anim(elem);
|
ret = await anim(elem);
|
||||||
}
|
}
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
|
@ -192,7 +192,7 @@ baz // undefined
|
|||||||
如果变量名与属性名不一致,必须写成下面这样。
|
如果变量名与属性名不一致,必须写成下面这样。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var { foo: baz } = { foo: 'aaa', bar: 'bbb' };
|
let { foo: baz } = { foo: 'aaa', bar: 'bbb' };
|
||||||
baz // "aaa"
|
baz // "aaa"
|
||||||
|
|
||||||
let obj = { first: 'hello', last: 'world' };
|
let obj = { first: 'hello', last: 'world' };
|
||||||
@ -251,7 +251,7 @@ p // ["Hello", {y: "World"}]
|
|||||||
下面是另一个例子。
|
下面是另一个例子。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var node = {
|
const node = {
|
||||||
loc: {
|
loc: {
|
||||||
start: {
|
start: {
|
||||||
line: 1,
|
line: 1,
|
||||||
@ -260,7 +260,7 @@ var node = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var { loc, loc: { start }, loc: { start: { line }} } = node;
|
let { loc, loc: { start }, loc: { start: { line }} } = node;
|
||||||
line // 1
|
line // 1
|
||||||
loc // Object {start: Object}
|
loc // Object {start: Object}
|
||||||
start // Object {line: 1, column: 5}
|
start // Object {line: 1, column: 5}
|
||||||
@ -642,7 +642,7 @@ jQuery.ajax = function (url, {
|
|||||||
任何部署了Iterator接口的对象,都可以用`for...of`循环遍历。Map结构原生支持Iterator接口,配合变量的解构赋值,获取键名和键值就非常方便。
|
任何部署了Iterator接口的对象,都可以用`for...of`循环遍历。Map结构原生支持Iterator接口,配合变量的解构赋值,获取键名和键值就非常方便。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var map = new Map();
|
const map = new Map();
|
||||||
map.set('first', 'hello');
|
map.set('first', 'hello');
|
||||||
map.set('second', 'world');
|
map.set('second', 'world');
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ function Point(x = 0, y = 0) {
|
|||||||
this.y = y;
|
this.y = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
var p = new Point();
|
const p = new Point();
|
||||||
p // { x: 0, y: 0 }
|
p // { x: 0, y: 0 }
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ ECMAScript 6.0(以下简称 ES6)是 JavaScript 语言的下一代标准,
|
|||||||
|
|
||||||
该标准从一开始就是针对 JavaScript 语言制定的,但是之所以不叫 JavaScript,有两个原因。一是商标,Java 是 Sun 公司的商标,根据授权协议,只有 Netscape 公司可以合法地使用 JavaScript 这个名字,且 JavaScript 本身也已经被 Netscape 公司注册为商标。二是想体现这门语言的制定者是 ECMA,不是 Netscape,这样有利于保证这门语言的开放性和中立性。
|
该标准从一开始就是针对 JavaScript 语言制定的,但是之所以不叫 JavaScript,有两个原因。一是商标,Java 是 Sun 公司的商标,根据授权协议,只有 Netscape 公司可以合法地使用 JavaScript 这个名字,且 JavaScript 本身也已经被 Netscape 公司注册为商标。二是想体现这门语言的制定者是 ECMA,不是 Netscape,这样有利于保证这门语言的开放性和中立性。
|
||||||
|
|
||||||
因此,ECMAScript 和 JavaScript 的关系是,前者是后者的规格,后者是前者的一种实现(另外的 ECMAScript 方言还有 Jscript 和 ActionScript)。日常场合,这两个词是可以互换的。
|
因此,ECMAScript 和 JavaScript 的关系是,前者是后者的规范,后者是前者的一种实现(另外的 ECMAScript 方言还有 Jscript 和 ActionScript)。日常场合,这两个词是可以互换的。
|
||||||
|
|
||||||
## ES6 与 ECMAScript 2015 的关系
|
## ES6 与 ECMAScript 2015 的关系
|
||||||
|
|
||||||
|
@ -5,12 +5,12 @@
|
|||||||
ES6 允许直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。
|
ES6 允许直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var foo = 'bar';
|
const foo = 'bar';
|
||||||
var baz = {foo};
|
const baz = {foo};
|
||||||
baz // {foo: "bar"}
|
baz // {foo: "bar"}
|
||||||
|
|
||||||
// 等同于
|
// 等同于
|
||||||
var baz = {foo: foo};
|
const baz = {foo: foo};
|
||||||
```
|
```
|
||||||
|
|
||||||
上面代码表明,ES6 允许在对象之中,直接写变量。这时,属性名为变量名, 属性值为变量的值。下面是另一个例子。
|
上面代码表明,ES6 允许在对象之中,直接写变量。这时,属性名为变量名, 属性值为变量的值。下面是另一个例子。
|
||||||
@ -32,7 +32,7 @@ f(1, 2) // Object {x: 1, y: 2}
|
|||||||
除了属性简写,方法也可以简写。
|
除了属性简写,方法也可以简写。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var o = {
|
const o = {
|
||||||
method() {
|
method() {
|
||||||
return "Hello!";
|
return "Hello!";
|
||||||
}
|
}
|
||||||
@ -40,7 +40,7 @@ var o = {
|
|||||||
|
|
||||||
// 等同于
|
// 等同于
|
||||||
|
|
||||||
var o = {
|
const o = {
|
||||||
method: function() {
|
method: function() {
|
||||||
return "Hello!";
|
return "Hello!";
|
||||||
}
|
}
|
||||||
@ -50,9 +50,9 @@ var o = {
|
|||||||
下面是一个实际的例子。
|
下面是一个实际的例子。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var birth = '2000/01/01';
|
let birth = '2000/01/01';
|
||||||
|
|
||||||
var Person = {
|
const Person = {
|
||||||
|
|
||||||
name: '张三',
|
name: '张三',
|
||||||
|
|
||||||
@ -69,8 +69,8 @@ var Person = {
|
|||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
function getPoint() {
|
function getPoint() {
|
||||||
var x = 1;
|
const x = 1;
|
||||||
var y = 10;
|
const y = 10;
|
||||||
return {x, y};
|
return {x, y};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,7 +81,7 @@ getPoint()
|
|||||||
CommonJS 模块输出一组变量,就非常合适使用简洁写法。
|
CommonJS 模块输出一组变量,就非常合适使用简洁写法。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var ms = {};
|
let ms = {};
|
||||||
|
|
||||||
function getItem (key) {
|
function getItem (key) {
|
||||||
return key in ms ? ms[key] : null;
|
return key in ms ? ms[key] : null;
|
||||||
@ -107,7 +107,7 @@ module.exports = {
|
|||||||
属性的赋值器(setter)和取值器(getter),事实上也是采用这种写法。
|
属性的赋值器(setter)和取值器(getter),事实上也是采用这种写法。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var cart = {
|
const cart = {
|
||||||
_wheels: 4,
|
_wheels: 4,
|
||||||
|
|
||||||
get wheels () {
|
get wheels () {
|
||||||
@ -126,7 +126,7 @@ var cart = {
|
|||||||
注意,简洁写法的属性名总是字符串,这会导致一些看上去比较奇怪的结果。
|
注意,简洁写法的属性名总是字符串,这会导致一些看上去比较奇怪的结果。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var obj = {
|
const obj = {
|
||||||
class () {}
|
class () {}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -142,7 +142,7 @@ var obj = {
|
|||||||
如果某个方法的值是一个 Generator 函数,前面需要加上星号。
|
如果某个方法的值是一个 Generator 函数,前面需要加上星号。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var obj = {
|
const obj = {
|
||||||
* m() {
|
* m() {
|
||||||
yield 'hello world';
|
yield 'hello world';
|
||||||
}
|
}
|
||||||
@ -186,9 +186,9 @@ let obj = {
|
|||||||
下面是另一个例子。
|
下面是另一个例子。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var lastWord = 'last word';
|
let lastWord = 'last word';
|
||||||
|
|
||||||
var a = {
|
const a = {
|
||||||
'first word': 'hello',
|
'first word': 'hello',
|
||||||
[lastWord]: 'world'
|
[lastWord]: 'world'
|
||||||
};
|
};
|
||||||
@ -214,13 +214,13 @@ obj.hello() // hi
|
|||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
// 报错
|
// 报错
|
||||||
var foo = 'bar';
|
const foo = 'bar';
|
||||||
var bar = 'abc';
|
const bar = 'abc';
|
||||||
var baz = { [foo] };
|
const baz = { [foo] };
|
||||||
|
|
||||||
// 正确
|
// 正确
|
||||||
var foo = 'bar';
|
const foo = 'bar';
|
||||||
var baz = { [foo]: 'abc'};
|
const baz = { [foo]: 'abc'};
|
||||||
```
|
```
|
||||||
|
|
||||||
注意,属性名表达式如果是一个对象,默认情况下会自动将对象转为字符串`[object Object]`,这一点要特别小心。
|
注意,属性名表达式如果是一个对象,默认情况下会自动将对象转为字符串`[object Object]`,这一点要特别小心。
|
||||||
@ -346,10 +346,10 @@ Object.defineProperty(Object, 'is', {
|
|||||||
`Object.assign`方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)。
|
`Object.assign`方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var target = { a: 1 };
|
const target = { a: 1 };
|
||||||
|
|
||||||
var source1 = { b: 2 };
|
const source1 = { b: 2 };
|
||||||
var source2 = { c: 3 };
|
const source2 = { c: 3 };
|
||||||
|
|
||||||
Object.assign(target, source1, source2);
|
Object.assign(target, source1, source2);
|
||||||
target // {a:1, b:2, c:3}
|
target // {a:1, b:2, c:3}
|
||||||
@ -360,10 +360,10 @@ target // {a:1, b:2, c:3}
|
|||||||
注意,如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性。
|
注意,如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var target = { a: 1, b: 1 };
|
const target = { a: 1, b: 1 };
|
||||||
|
|
||||||
var source1 = { b: 2, c: 2 };
|
const source1 = { b: 2, c: 2 };
|
||||||
var source2 = { c: 3 };
|
const source2 = { c: 3 };
|
||||||
|
|
||||||
Object.assign(target, source1, source2);
|
Object.assign(target, source1, source2);
|
||||||
target // {a:1, b:2, c:3}
|
target // {a:1, b:2, c:3}
|
||||||
@ -372,7 +372,7 @@ target // {a:1, b:2, c:3}
|
|||||||
如果只有一个参数,`Object.assign`会直接返回该参数。
|
如果只有一个参数,`Object.assign`会直接返回该参数。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var obj = {a: 1};
|
const obj = {a: 1};
|
||||||
Object.assign(obj) === obj // true
|
Object.assign(obj) === obj // true
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -400,11 +400,11 @@ Object.assign(obj, null) === obj // true
|
|||||||
其他类型的值(即数值、字符串和布尔值)不在首参数,也不会报错。但是,除了字符串会以数组形式,拷贝入目标对象,其他值都不会产生效果。
|
其他类型的值(即数值、字符串和布尔值)不在首参数,也不会报错。但是,除了字符串会以数组形式,拷贝入目标对象,其他值都不会产生效果。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var v1 = 'abc';
|
const v1 = 'abc';
|
||||||
var v2 = true;
|
const v2 = true;
|
||||||
var v3 = 10;
|
const v3 = 10;
|
||||||
|
|
||||||
var obj = Object.assign({}, v1, v2, v3);
|
const obj = Object.assign({}, v1, v2, v3);
|
||||||
console.log(obj); // { "0": "a", "1": "b", "2": "c" }
|
console.log(obj); // { "0": "a", "1": "b", "2": "c" }
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -444,8 +444,8 @@ Object.assign({ a: 'b' }, { [Symbol('c')]: 'd' })
|
|||||||
`Object.assign`方法实行的是浅拷贝,而不是深拷贝。也就是说,如果源对象某个属性的值是对象,那么目标对象拷贝得到的是这个对象的引用。
|
`Object.assign`方法实行的是浅拷贝,而不是深拷贝。也就是说,如果源对象某个属性的值是对象,那么目标对象拷贝得到的是这个对象的引用。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var obj1 = {a: {b: 1}};
|
const obj1 = {a: {b: 1}};
|
||||||
var obj2 = Object.assign({}, obj1);
|
const obj2 = Object.assign({}, obj1);
|
||||||
|
|
||||||
obj1.a.b = 2;
|
obj1.a.b = 2;
|
||||||
obj2.a.b // 2
|
obj2.a.b // 2
|
||||||
@ -456,8 +456,8 @@ obj2.a.b // 2
|
|||||||
对于这种嵌套的对象,一旦遇到同名属性,`Object.assign`的处理方法是替换,而不是添加。
|
对于这种嵌套的对象,一旦遇到同名属性,`Object.assign`的处理方法是替换,而不是添加。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var target = { a: { b: 'c', d: 'e' } }
|
const target = { a: { b: 'c', d: 'e' } }
|
||||||
var source = { a: { b: 'hello' } }
|
const source = { a: { b: 'hello' } }
|
||||||
Object.assign(target, source)
|
Object.assign(target, source)
|
||||||
// { a: { b: 'hello' } }
|
// { a: { b: 'hello' } }
|
||||||
```
|
```
|
||||||
@ -838,7 +838,7 @@ d.a // "a"
|
|||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
// es6的写法
|
// es6的写法
|
||||||
var obj = {
|
const obj = {
|
||||||
method: function() { ... }
|
method: function() { ... }
|
||||||
};
|
};
|
||||||
obj.__proto__ = someOtherObj;
|
obj.__proto__ = someOtherObj;
|
||||||
@ -895,7 +895,7 @@ Object.getPrototypeOf({ __proto__: null })
|
|||||||
Object.setPrototypeOf(object, prototype)
|
Object.setPrototypeOf(object, prototype)
|
||||||
|
|
||||||
// 用法
|
// 用法
|
||||||
var o = Object.setPrototypeOf({}, null);
|
const o = Object.setPrototypeOf({}, null);
|
||||||
```
|
```
|
||||||
|
|
||||||
该方法等同于下面的函数。
|
该方法等同于下面的函数。
|
||||||
@ -957,7 +957,7 @@ function Rectangle() {
|
|||||||
// ...
|
// ...
|
||||||
}
|
}
|
||||||
|
|
||||||
var rec = new Rectangle();
|
const rec = new Rectangle();
|
||||||
|
|
||||||
Object.getPrototypeOf(rec) === Rectangle.prototype
|
Object.getPrototypeOf(rec) === Rectangle.prototype
|
||||||
// true
|
// true
|
||||||
@ -1033,7 +1033,7 @@ for (let [key, value] of entries(obj)) {
|
|||||||
`Object.values`方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值。
|
`Object.values`方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var obj = { foo: 'bar', baz: 42 };
|
const obj = { foo: 'bar', baz: 42 };
|
||||||
Object.values(obj)
|
Object.values(obj)
|
||||||
// ["bar", 42]
|
// ["bar", 42]
|
||||||
```
|
```
|
||||||
@ -1041,7 +1041,7 @@ Object.values(obj)
|
|||||||
返回数组的成员顺序,与本章的《属性的遍历》部分介绍的排列规则一致。
|
返回数组的成员顺序,与本章的《属性的遍历》部分介绍的排列规则一致。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var obj = { 100: 'a', 2: 'b', 7: 'c' };
|
const obj = { 100: 'a', 2: 'b', 7: 'c' };
|
||||||
Object.values(obj)
|
Object.values(obj)
|
||||||
// ["b", "c", "a"]
|
// ["b", "c", "a"]
|
||||||
```
|
```
|
||||||
@ -1051,14 +1051,14 @@ Object.values(obj)
|
|||||||
`Object.values`只返回对象自身的可遍历属性。
|
`Object.values`只返回对象自身的可遍历属性。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var obj = Object.create({}, {p: {value: 42}});
|
const obj = Object.create({}, {p: {value: 42}});
|
||||||
Object.values(obj) // []
|
Object.values(obj) // []
|
||||||
```
|
```
|
||||||
|
|
||||||
上面代码中,`Object.create`方法的第二个参数添加的对象属性(属性`p`),如果不显式声明,默认是不可遍历的,因为`p`的属性描述对象的`enumerable`默认是`false`,`Object.values`不会返回这个属性。只要把`enumerable`改成`true`,`Object.values`就会返回属性`p`的值。
|
上面代码中,`Object.create`方法的第二个参数添加的对象属性(属性`p`),如果不显式声明,默认是不可遍历的,因为`p`的属性描述对象的`enumerable`默认是`false`,`Object.values`不会返回这个属性。只要把`enumerable`改成`true`,`Object.values`就会返回属性`p`的值。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var obj = Object.create({}, {p:
|
const obj = Object.create({}, {p:
|
||||||
{
|
{
|
||||||
value: 42,
|
value: 42,
|
||||||
enumerable: true
|
enumerable: true
|
||||||
@ -1095,7 +1095,7 @@ Object.values(true) // []
|
|||||||
`Object.entries`方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值对数组。
|
`Object.entries`方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值对数组。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var obj = { foo: 'bar', baz: 42 };
|
const obj = { foo: 'bar', baz: 42 };
|
||||||
Object.entries(obj)
|
Object.entries(obj)
|
||||||
// [ ["foo", "bar"], ["baz", 42] ]
|
// [ ["foo", "bar"], ["baz", 42] ]
|
||||||
```
|
```
|
||||||
@ -1127,8 +1127,8 @@ for (let [k, v] of Object.entries(obj)) {
|
|||||||
`Object.entries`方法的另一个用处是,将对象转为真正的`Map`结构。
|
`Object.entries`方法的另一个用处是,将对象转为真正的`Map`结构。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var obj = { foo: 'bar', baz: 42 };
|
const obj = { foo: 'bar', baz: 42 };
|
||||||
var map = new Map(Object.entries(obj));
|
const map = new Map(Object.entries(obj));
|
||||||
map // Map { foo: "bar", baz: 42 }
|
map // Map { foo: "bar", baz: 42 }
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -1220,7 +1220,7 @@ o3.a // undefined
|
|||||||
下面是另一个例子。
|
下面是另一个例子。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var o = Object.create({ x: 1, y: 2 });
|
const o = Object.create({ x: 1, y: 2 });
|
||||||
o.z = 3;
|
o.z = 3;
|
||||||
|
|
||||||
let { x, ...{ y, z } } = o;
|
let { x, ...{ y, z } } = o;
|
||||||
|
@ -70,7 +70,7 @@ s.charCodeAt(1) // 57271
|
|||||||
ES6提供了`codePointAt`方法,能够正确处理4个字节储存的字符,返回一个字符的码点。
|
ES6提供了`codePointAt`方法,能够正确处理4个字节储存的字符,返回一个字符的码点。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var s = '𠮷a';
|
let s = '𠮷a';
|
||||||
|
|
||||||
s.codePointAt(0) // 134071
|
s.codePointAt(0) // 134071
|
||||||
s.codePointAt(1) // 57271
|
s.codePointAt(1) // 57271
|
||||||
@ -85,7 +85,7 @@ s.codePointAt(2) // 97
|
|||||||
`codePointAt`方法返回的是码点的十进制值,如果想要十六进制的值,可以使用`toString`方法转换一下。
|
`codePointAt`方法返回的是码点的十进制值,如果想要十六进制的值,可以使用`toString`方法转换一下。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var s = '𠮷a';
|
let s = '𠮷a';
|
||||||
|
|
||||||
s.codePointAt(0).toString(16) // "20bb7"
|
s.codePointAt(0).toString(16) // "20bb7"
|
||||||
s.codePointAt(2).toString(16) // "61"
|
s.codePointAt(2).toString(16) // "61"
|
||||||
@ -94,7 +94,7 @@ s.codePointAt(2).toString(16) // "61"
|
|||||||
你可能注意到了,`codePointAt`方法的参数,仍然是不正确的。比如,上面代码中,字符`a`在字符串`s`的正确位置序号应该是1,但是必须向`codePointAt`方法传入2。解决这个问题的一个办法是使用`for...of`循环,因为它会正确识别32位的UTF-16字符。
|
你可能注意到了,`codePointAt`方法的参数,仍然是不正确的。比如,上面代码中,字符`a`在字符串`s`的正确位置序号应该是1,但是必须向`codePointAt`方法传入2。解决这个问题的一个办法是使用`for...of`循环,因为它会正确识别32位的UTF-16字符。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var s = '𠮷a';
|
let s = '𠮷a';
|
||||||
for (let ch of s) {
|
for (let ch of s) {
|
||||||
console.log(ch.codePointAt(0).toString(16));
|
console.log(ch.codePointAt(0).toString(16));
|
||||||
}
|
}
|
||||||
@ -153,7 +153,7 @@ for (let codePoint of 'foo') {
|
|||||||
除了遍历字符串,这个遍历器最大的优点是可以识别大于`0xFFFF`的码点,传统的`for`循环无法识别这样的码点。
|
除了遍历字符串,这个遍历器最大的优点是可以识别大于`0xFFFF`的码点,传统的`for`循环无法识别这样的码点。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var text = String.fromCodePoint(0x20BB7);
|
let text = String.fromCodePoint(0x20BB7);
|
||||||
|
|
||||||
for (let i = 0; i < text.length; i++) {
|
for (let i = 0; i < text.length; i++) {
|
||||||
console.log(text[i]);
|
console.log(text[i]);
|
||||||
@ -236,7 +236,7 @@ ES6 提供字符串实例的`normalize()`方法,用来将字符的不同表示
|
|||||||
- **endsWith()**:返回布尔值,表示参数字符串是否在原字符串的尾部。
|
- **endsWith()**:返回布尔值,表示参数字符串是否在原字符串的尾部。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var s = 'Hello world!';
|
let s = 'Hello world!';
|
||||||
|
|
||||||
s.startsWith('Hello') // true
|
s.startsWith('Hello') // true
|
||||||
s.endsWith('!') // true
|
s.endsWith('!') // true
|
||||||
@ -246,7 +246,7 @@ s.includes('o') // true
|
|||||||
这三个方法都支持第二个参数,表示开始搜索的位置。
|
这三个方法都支持第二个参数,表示开始搜索的位置。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var s = 'Hello world!';
|
let s = 'Hello world!';
|
||||||
|
|
||||||
s.startsWith('world', 6) // true
|
s.startsWith('world', 6) // true
|
||||||
s.endsWith('Hello', 5) // true
|
s.endsWith('Hello', 5) // true
|
||||||
@ -386,14 +386,14 @@ console.log(`string text line 1
|
|||||||
string text line 2`);
|
string text line 2`);
|
||||||
|
|
||||||
// 字符串中嵌入变量
|
// 字符串中嵌入变量
|
||||||
var name = "Bob", time = "today";
|
let name = "Bob", time = "today";
|
||||||
`Hello ${name}, how are you ${time}?`
|
`Hello ${name}, how are you ${time}?`
|
||||||
```
|
```
|
||||||
|
|
||||||
上面代码中的模板字符串,都是用反引号表示。如果在模板字符串中需要使用反引号,则前面要用反斜杠转义。
|
上面代码中的模板字符串,都是用反引号表示。如果在模板字符串中需要使用反引号,则前面要用反斜杠转义。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var greeting = `\`Yo\` World!`;
|
let greeting = `\`Yo\` World!`;
|
||||||
```
|
```
|
||||||
|
|
||||||
如果使用模板字符串表示多行字符串,所有的空格和缩进都会被保留在输出之中。
|
如果使用模板字符串表示多行字符串,所有的空格和缩进都会被保留在输出之中。
|
||||||
@ -439,8 +439,8 @@ function authorize(user, action) {
|
|||||||
大括号内部可以放入任意的JavaScript表达式,可以进行运算,以及引用对象属性。
|
大括号内部可以放入任意的JavaScript表达式,可以进行运算,以及引用对象属性。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var x = 1;
|
let x = 1;
|
||||||
var y = 2;
|
let y = 2;
|
||||||
|
|
||||||
`${x} + ${y} = ${x + y}`
|
`${x} + ${y} = ${x + y}`
|
||||||
// "1 + 2 = 3"
|
// "1 + 2 = 3"
|
||||||
@ -448,7 +448,7 @@ var y = 2;
|
|||||||
`${x} + ${y * 2} = ${x + y * 2}`
|
`${x} + ${y * 2} = ${x + y * 2}`
|
||||||
// "1 + 4 = 5"
|
// "1 + 4 = 5"
|
||||||
|
|
||||||
var obj = {x: 1, y: 2};
|
let obj = {x: 1, y: 2};
|
||||||
`${obj.x + obj.y}`
|
`${obj.x + obj.y}`
|
||||||
// "3"
|
// "3"
|
||||||
```
|
```
|
||||||
@ -470,7 +470,7 @@ function fn() {
|
|||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
// 变量place没有声明
|
// 变量place没有声明
|
||||||
var msg = `Hello, ${place}`;
|
let msg = `Hello, ${place}`;
|
||||||
// 报错
|
// 报错
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -533,9 +533,9 @@ func('Jack') // "Hello Jack!"
|
|||||||
下面,我们来看一个通过模板字符串,生成正式模板的实例。
|
下面,我们来看一个通过模板字符串,生成正式模板的实例。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var template = `
|
let template = `
|
||||||
<ul>
|
<ul>
|
||||||
<% for(var i=0; i < data.supplies.length; i++) { %>
|
<% for(let i=0; i < data.supplies.length; i++) { %>
|
||||||
<li><%= data.supplies[i] %></li>
|
<li><%= data.supplies[i] %></li>
|
||||||
<% } %>
|
<% } %>
|
||||||
</ul>
|
</ul>
|
||||||
@ -550,7 +550,7 @@ var template = `
|
|||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
echo('<ul>');
|
echo('<ul>');
|
||||||
for(var i=0; i < data.supplies.length; i++) {
|
for(let i=0; i < data.supplies.length; i++) {
|
||||||
echo('<li>');
|
echo('<li>');
|
||||||
echo(data.supplies[i]);
|
echo(data.supplies[i]);
|
||||||
echo('</li>');
|
echo('</li>');
|
||||||
@ -561,8 +561,8 @@ echo('</ul>');
|
|||||||
这个转换使用正则表达式就行了。
|
这个转换使用正则表达式就行了。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var evalExpr = /<%=(.+?)%>/g;
|
let evalExpr = /<%=(.+?)%>/g;
|
||||||
var expr = /<%([\s\S]+?)%>/g;
|
let expr = /<%([\s\S]+?)%>/g;
|
||||||
|
|
||||||
template = template
|
template = template
|
||||||
.replace(evalExpr, '`); \n echo( $1 ); \n echo(`')
|
.replace(evalExpr, '`); \n echo( $1 ); \n echo(`')
|
||||||
@ -574,9 +574,9 @@ template = 'echo(`' + template + '`);';
|
|||||||
然后,将`template`封装在一个函数里面返回,就可以了。
|
然后,将`template`封装在一个函数里面返回,就可以了。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var script =
|
let script =
|
||||||
`(function parse(data){
|
`(function parse(data){
|
||||||
var output = "";
|
let output = "";
|
||||||
|
|
||||||
function echo(html){
|
function echo(html){
|
||||||
output += html;
|
output += html;
|
||||||
@ -594,8 +594,8 @@ return script;
|
|||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
function compile(template){
|
function compile(template){
|
||||||
var evalExpr = /<%=(.+?)%>/g;
|
const evalExpr = /<%=(.+?)%>/g;
|
||||||
var expr = /<%([\s\S]+?)%>/g;
|
const expr = /<%([\s\S]+?)%>/g;
|
||||||
|
|
||||||
template = template
|
template = template
|
||||||
.replace(evalExpr, '`); \n echo( $1 ); \n echo(`')
|
.replace(evalExpr, '`); \n echo( $1 ); \n echo(`')
|
||||||
@ -603,9 +603,9 @@ function compile(template){
|
|||||||
|
|
||||||
template = 'echo(`' + template + '`);';
|
template = 'echo(`' + template + '`);';
|
||||||
|
|
||||||
var script =
|
let script =
|
||||||
`(function parse(data){
|
`(function parse(data){
|
||||||
var output = "";
|
let output = "";
|
||||||
|
|
||||||
function echo(html){
|
function echo(html){
|
||||||
output += html;
|
output += html;
|
||||||
@ -623,7 +623,7 @@ function compile(template){
|
|||||||
`compile`函数的用法如下。
|
`compile`函数的用法如下。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var parse = eval(compile(template));
|
let parse = eval(compile(template));
|
||||||
div.innerHTML = parse({ supplies: [ "broom", "mop", "cleaner" ] });
|
div.innerHTML = parse({ supplies: [ "broom", "mop", "cleaner" ] });
|
||||||
// <ul>
|
// <ul>
|
||||||
// <li>broom</li>
|
// <li>broom</li>
|
||||||
@ -647,8 +647,8 @@ alert(123)
|
|||||||
但是,如果模板字符里面有变量,就不是简单的调用了,而是会将模板字符串先处理成多个参数,再调用函数。
|
但是,如果模板字符里面有变量,就不是简单的调用了,而是会将模板字符串先处理成多个参数,再调用函数。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var a = 5;
|
let a = 5;
|
||||||
var b = 10;
|
let b = 10;
|
||||||
|
|
||||||
tag`Hello ${ a + b } world ${ a * b }`;
|
tag`Hello ${ a + b } world ${ a * b }`;
|
||||||
// 等同于
|
// 等同于
|
||||||
@ -690,8 +690,8 @@ tag(['Hello ', ' world ', ''], 15, 50)
|
|||||||
我们可以按照需要编写`tag`函数的代码。下面是`tag`函数的一种写法,以及运行结果。
|
我们可以按照需要编写`tag`函数的代码。下面是`tag`函数的一种写法,以及运行结果。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var a = 5;
|
let a = 5;
|
||||||
var b = 10;
|
let b = 10;
|
||||||
|
|
||||||
function tag(s, v1, v2) {
|
function tag(s, v1, v2) {
|
||||||
console.log(s[0]);
|
console.log(s[0]);
|
||||||
@ -715,12 +715,12 @@ tag`Hello ${ a + b } world ${ a * b}`;
|
|||||||
下面是一个更复杂的例子。
|
下面是一个更复杂的例子。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var total = 30;
|
let total = 30;
|
||||||
var msg = passthru`The total is ${total} (${total*1.05} with tax)`;
|
let msg = passthru`The total is ${total} (${total*1.05} with tax)`;
|
||||||
|
|
||||||
function passthru(literals) {
|
function passthru(literals) {
|
||||||
var result = '';
|
let result = '';
|
||||||
var i = 0;
|
let i = 0;
|
||||||
|
|
||||||
while (i < literals.length) {
|
while (i < literals.length) {
|
||||||
result += literals[i++];
|
result += literals[i++];
|
||||||
@ -741,8 +741,8 @@ msg // "The total is 30 (31.5 with tax)"
|
|||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
function passthru(literals, ...values) {
|
function passthru(literals, ...values) {
|
||||||
var output = "";
|
let output = "";
|
||||||
for (var index = 0; index < values.length; index++) {
|
for (let index = 0; index < values.length; index++) {
|
||||||
output += literals[index] + values[index];
|
output += literals[index] + values[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -754,13 +754,13 @@ function passthru(literals, ...values) {
|
|||||||
“标签模板”的一个重要应用,就是过滤HTML字符串,防止用户输入恶意内容。
|
“标签模板”的一个重要应用,就是过滤HTML字符串,防止用户输入恶意内容。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var message =
|
let message =
|
||||||
SaferHTML`<p>${sender} has sent you a message.</p>`;
|
SaferHTML`<p>${sender} has sent you a message.</p>`;
|
||||||
|
|
||||||
function SaferHTML(templateData) {
|
function SaferHTML(templateData) {
|
||||||
var s = templateData[0];
|
let s = templateData[0];
|
||||||
for (var i = 1; i < arguments.length; i++) {
|
for (let i = 1; i < arguments.length; i++) {
|
||||||
var arg = String(arguments[i]);
|
let arg = String(arguments[i]);
|
||||||
|
|
||||||
// Escape special characters in the substitution.
|
// Escape special characters in the substitution.
|
||||||
s += arg.replace(/&/g, "&")
|
s += arg.replace(/&/g, "&")
|
||||||
@ -777,8 +777,8 @@ function SaferHTML(templateData) {
|
|||||||
上面代码中,`sender`变量往往是用户提供的,经过`SaferHTML`函数处理,里面的特殊字符都会被转义。
|
上面代码中,`sender`变量往往是用户提供的,经过`SaferHTML`函数处理,里面的特殊字符都会被转义。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var sender = '<script>alert("abc")</script>'; // 恶意代码
|
let sender = '<script>alert("abc")</script>'; // 恶意代码
|
||||||
var message = SaferHTML`<p>${sender} has sent you a message.</p>`;
|
let message = SaferHTML`<p>${sender} has sent you a message.</p>`;
|
||||||
|
|
||||||
message
|
message
|
||||||
// <p><script>alert("abc")</script> has sent you a message.</p>
|
// <p><script>alert("abc")</script> has sent you a message.</p>
|
||||||
@ -797,7 +797,7 @@ i18n`Welcome to ${siteName}, you are visitor number ${visitorNumber}!`
|
|||||||
```javascript
|
```javascript
|
||||||
// 下面的hashTemplate函数
|
// 下面的hashTemplate函数
|
||||||
// 是一个自定义的模板处理函数
|
// 是一个自定义的模板处理函数
|
||||||
var libraryHtml = hashTemplate`
|
let libraryHtml = hashTemplate`
|
||||||
<ul>
|
<ul>
|
||||||
#for book in ${myBooks}
|
#for book in ${myBooks}
|
||||||
<li><i>#{book.title}</i> by #{book.author}</li>
|
<li><i>#{book.title}</i> by #{book.author}</li>
|
||||||
@ -883,8 +883,8 @@ String.raw`Hi\\n`
|
|||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
String.raw = function (strings, ...values) {
|
String.raw = function (strings, ...values) {
|
||||||
var output = "";
|
let output = "";
|
||||||
for (var index = 0; index < values.length; index++) {
|
for (let index = 0; index < values.length; index++) {
|
||||||
output += strings.raw[index] + values[index];
|
output += strings.raw[index] + values[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,8 +22,8 @@ typeof s
|
|||||||
`Symbol`函数可以接受一个字符串作为参数,表示对 Symbol 实例的描述,主要是为了在控制台显示,或者转为字符串时,比较容易区分。
|
`Symbol`函数可以接受一个字符串作为参数,表示对 Symbol 实例的描述,主要是为了在控制台显示,或者转为字符串时,比较容易区分。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var s1 = Symbol('foo');
|
let s1 = Symbol('foo');
|
||||||
var s2 = Symbol('bar');
|
let s2 = Symbol('bar');
|
||||||
|
|
||||||
s1 // Symbol(foo)
|
s1 // Symbol(foo)
|
||||||
s2 // Symbol(bar)
|
s2 // Symbol(bar)
|
||||||
@ -50,14 +50,14 @@ sym // Symbol(abc)
|
|||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
// 没有参数的情况
|
// 没有参数的情况
|
||||||
var s1 = Symbol();
|
let s1 = Symbol();
|
||||||
var s2 = Symbol();
|
let s2 = Symbol();
|
||||||
|
|
||||||
s1 === s2 // false
|
s1 === s2 // false
|
||||||
|
|
||||||
// 有参数的情况
|
// 有参数的情况
|
||||||
var s1 = Symbol('foo');
|
let s1 = Symbol('foo');
|
||||||
var s2 = Symbol('foo');
|
let s2 = Symbol('foo');
|
||||||
|
|
||||||
s1 === s2 // false
|
s1 === s2 // false
|
||||||
```
|
```
|
||||||
@ -67,7 +67,7 @@ s1 === s2 // false
|
|||||||
Symbol 值不能与其他类型的值进行运算,会报错。
|
Symbol 值不能与其他类型的值进行运算,会报错。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var sym = Symbol('My symbol');
|
let sym = Symbol('My symbol');
|
||||||
|
|
||||||
"your symbol is " + sym
|
"your symbol is " + sym
|
||||||
// TypeError: can't convert symbol to string
|
// TypeError: can't convert symbol to string
|
||||||
@ -78,7 +78,7 @@ var sym = Symbol('My symbol');
|
|||||||
但是,Symbol 值可以显式转为字符串。
|
但是,Symbol 值可以显式转为字符串。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var sym = Symbol('My symbol');
|
let sym = Symbol('My symbol');
|
||||||
|
|
||||||
String(sym) // 'Symbol(My symbol)'
|
String(sym) // 'Symbol(My symbol)'
|
||||||
sym.toString() // 'Symbol(My symbol)'
|
sym.toString() // 'Symbol(My symbol)'
|
||||||
@ -87,7 +87,7 @@ sym.toString() // 'Symbol(My symbol)'
|
|||||||
另外,Symbol 值也可以转为布尔值,但是不能转为数值。
|
另外,Symbol 值也可以转为布尔值,但是不能转为数值。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var sym = Symbol();
|
let sym = Symbol();
|
||||||
Boolean(sym) // true
|
Boolean(sym) // true
|
||||||
!sym // false
|
!sym // false
|
||||||
|
|
||||||
@ -104,19 +104,19 @@ sym + 2 // TypeError
|
|||||||
由于每一个 Symbol 值都是不相等的,这意味着 Symbol 值可以作为标识符,用于对象的属性名,就能保证不会出现同名的属性。这对于一个对象由多个模块构成的情况非常有用,能防止某一个键被不小心改写或覆盖。
|
由于每一个 Symbol 值都是不相等的,这意味着 Symbol 值可以作为标识符,用于对象的属性名,就能保证不会出现同名的属性。这对于一个对象由多个模块构成的情况非常有用,能防止某一个键被不小心改写或覆盖。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var mySymbol = Symbol();
|
let mySymbol = Symbol();
|
||||||
|
|
||||||
// 第一种写法
|
// 第一种写法
|
||||||
var a = {};
|
let a = {};
|
||||||
a[mySymbol] = 'Hello!';
|
a[mySymbol] = 'Hello!';
|
||||||
|
|
||||||
// 第二种写法
|
// 第二种写法
|
||||||
var a = {
|
let a = {
|
||||||
[mySymbol]: 'Hello!'
|
[mySymbol]: 'Hello!'
|
||||||
};
|
};
|
||||||
|
|
||||||
// 第三种写法
|
// 第三种写法
|
||||||
var a = {};
|
let a = {};
|
||||||
Object.defineProperty(a, mySymbol, { value: 'Hello!' });
|
Object.defineProperty(a, mySymbol, { value: 'Hello!' });
|
||||||
|
|
||||||
// 以上写法都得到同样结果
|
// 以上写法都得到同样结果
|
||||||
@ -128,8 +128,8 @@ a[mySymbol] // "Hello!"
|
|||||||
注意,Symbol 值作为对象属性名时,不能用点运算符。
|
注意,Symbol 值作为对象属性名时,不能用点运算符。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var mySymbol = Symbol();
|
const mySymbol = Symbol();
|
||||||
var a = {};
|
const a = {};
|
||||||
|
|
||||||
a.mySymbol = 'Hello!';
|
a.mySymbol = 'Hello!';
|
||||||
a[mySymbol] // undefined
|
a[mySymbol] // undefined
|
||||||
@ -200,7 +200,7 @@ function getComplement(color) {
|
|||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
function getArea(shape, options) {
|
function getArea(shape, options) {
|
||||||
var area = 0;
|
let area = 0;
|
||||||
|
|
||||||
switch (shape) {
|
switch (shape) {
|
||||||
case 'Triangle': // 魔术字符串
|
case 'Triangle': // 魔术字符串
|
||||||
@ -220,12 +220,12 @@ getArea('Triangle', { width: 100, height: 100 }); // 魔术字符串
|
|||||||
常用的消除魔术字符串的方法,就是把它写成一个变量。
|
常用的消除魔术字符串的方法,就是把它写成一个变量。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var shapeType = {
|
const shapeType = {
|
||||||
triangle: 'Triangle'
|
triangle: 'Triangle'
|
||||||
};
|
};
|
||||||
|
|
||||||
function getArea(shape, options) {
|
function getArea(shape, options) {
|
||||||
var area = 0;
|
let area = 0;
|
||||||
switch (shape) {
|
switch (shape) {
|
||||||
case shapeType.triangle:
|
case shapeType.triangle:
|
||||||
area = .5 * options.width * options.height;
|
area = .5 * options.width * options.height;
|
||||||
@ -256,14 +256,14 @@ Symbol 作为属性名,该属性不会出现在`for...in`、`for...of`循环
|
|||||||
`Object.getOwnPropertySymbols`方法返回一个数组,成员是当前对象的所有用作属性名的 Symbol 值。
|
`Object.getOwnPropertySymbols`方法返回一个数组,成员是当前对象的所有用作属性名的 Symbol 值。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var obj = {};
|
const obj = {};
|
||||||
var a = Symbol('a');
|
let a = Symbol('a');
|
||||||
var b = Symbol('b');
|
let b = Symbol('b');
|
||||||
|
|
||||||
obj[a] = 'Hello';
|
obj[a] = 'Hello';
|
||||||
obj[b] = 'World';
|
obj[b] = 'World';
|
||||||
|
|
||||||
var objectSymbols = Object.getOwnPropertySymbols(obj);
|
const objectSymbols = Object.getOwnPropertySymbols(obj);
|
||||||
|
|
||||||
objectSymbols
|
objectSymbols
|
||||||
// [Symbol(a), Symbol(b)]
|
// [Symbol(a), Symbol(b)]
|
||||||
@ -272,15 +272,15 @@ objectSymbols
|
|||||||
下面是另一个例子,`Object.getOwnPropertySymbols`方法与`for...in`循环、`Object.getOwnPropertyNames`方法进行对比的例子。
|
下面是另一个例子,`Object.getOwnPropertySymbols`方法与`for...in`循环、`Object.getOwnPropertyNames`方法进行对比的例子。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var obj = {};
|
const obj = {};
|
||||||
|
|
||||||
var foo = Symbol("foo");
|
let foo = Symbol("foo");
|
||||||
|
|
||||||
Object.defineProperty(obj, foo, {
|
Object.defineProperty(obj, foo, {
|
||||||
value: "foobar",
|
value: "foobar",
|
||||||
});
|
});
|
||||||
|
|
||||||
for (var i in obj) {
|
for (let i in obj) {
|
||||||
console.log(i); // 无输出
|
console.log(i); // 无输出
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -309,7 +309,7 @@ Reflect.ownKeys(obj)
|
|||||||
由于以 Symbol 值作为名称的属性,不会被常规方法遍历得到。我们可以利用这个特性,为对象定义一些非私有的、但又希望只用于内部的方法。
|
由于以 Symbol 值作为名称的属性,不会被常规方法遍历得到。我们可以利用这个特性,为对象定义一些非私有的、但又希望只用于内部的方法。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var size = Symbol('size');
|
let size = Symbol('size');
|
||||||
|
|
||||||
class Collection {
|
class Collection {
|
||||||
constructor() {
|
constructor() {
|
||||||
@ -326,7 +326,7 @@ class Collection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var x = new Collection();
|
let x = new Collection();
|
||||||
Collection.sizeOf(x) // 0
|
Collection.sizeOf(x) // 0
|
||||||
|
|
||||||
x.add('foo');
|
x.add('foo');
|
||||||
@ -344,8 +344,8 @@ Object.getOwnPropertySymbols(x) // [Symbol(size)]
|
|||||||
有时,我们希望重新使用同一个Symbol值,`Symbol.for`方法可以做到这一点。它接受一个字符串作为参数,然后搜索有没有以该参数作为名称的Symbol值。如果有,就返回这个Symbol值,否则就新建并返回一个以该字符串为名称的Symbol值。
|
有时,我们希望重新使用同一个Symbol值,`Symbol.for`方法可以做到这一点。它接受一个字符串作为参数,然后搜索有没有以该参数作为名称的Symbol值。如果有,就返回这个Symbol值,否则就新建并返回一个以该字符串为名称的Symbol值。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var s1 = Symbol.for('foo');
|
let s1 = Symbol.for('foo');
|
||||||
var s2 = Symbol.for('foo');
|
let s2 = Symbol.for('foo');
|
||||||
|
|
||||||
s1 === s2 // true
|
s1 === s2 // true
|
||||||
```
|
```
|
||||||
@ -367,10 +367,10 @@ Symbol("bar") === Symbol("bar")
|
|||||||
`Symbol.keyFor`方法返回一个已登记的 Symbol 类型值的`key`。
|
`Symbol.keyFor`方法返回一个已登记的 Symbol 类型值的`key`。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var s1 = Symbol.for("foo");
|
let s1 = Symbol.for("foo");
|
||||||
Symbol.keyFor(s1) // "foo"
|
Symbol.keyFor(s1) // "foo"
|
||||||
|
|
||||||
var s2 = Symbol("foo");
|
let s2 = Symbol("foo");
|
||||||
Symbol.keyFor(s2) // undefined
|
Symbol.keyFor(s2) // undefined
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -413,7 +413,7 @@ module.exports = global._foo;
|
|||||||
然后,加载上面的`mod.js`。
|
然后,加载上面的`mod.js`。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var a = require('./mod.js');
|
const a = require('./mod.js');
|
||||||
console.log(a.foo);
|
console.log(a.foo);
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -422,7 +422,7 @@ console.log(a.foo);
|
|||||||
但是,这里有一个问题,全局变量`global._foo`是可写的,任何文件都可以修改。
|
但是,这里有一个问题,全局变量`global._foo`是可写的,任何文件都可以修改。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var a = require('./mod.js');
|
const a = require('./mod.js');
|
||||||
global._foo = 123;
|
global._foo = 123;
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -448,7 +448,7 @@ module.exports = global[FOO_KEY];
|
|||||||
上面代码中,可以保证`global[FOO_KEY]`不会被无意间覆盖,但还是可以被改写。
|
上面代码中,可以保证`global[FOO_KEY]`不会被无意间覆盖,但还是可以被改写。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var a = require('./mod.js');
|
const a = require('./mod.js');
|
||||||
global[Symbol.for('foo')] = 123;
|
global[Symbol.for('foo')] = 123;
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -581,8 +581,8 @@ static get [Symbol.species]() {
|
|||||||
class MyArray extends Array {
|
class MyArray extends Array {
|
||||||
static get [Symbol.species]() { return Array; }
|
static get [Symbol.species]() { return Array; }
|
||||||
}
|
}
|
||||||
var a = new MyArray(1,2,3);
|
let a = new MyArray(1,2,3);
|
||||||
var mapped = a.map(x => x * x);
|
let mapped = a.map(x => x * x);
|
||||||
|
|
||||||
mapped instanceof MyArray // false
|
mapped instanceof MyArray // false
|
||||||
mapped instanceof Array // true
|
mapped instanceof Array // true
|
||||||
@ -667,7 +667,7 @@ class MySplitter {
|
|||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
[Symbol.split](string) {
|
[Symbol.split](string) {
|
||||||
var index = string.indexOf(this.value);
|
let index = string.indexOf(this.value);
|
||||||
if (index === -1) {
|
if (index === -1) {
|
||||||
return string;
|
return string;
|
||||||
}
|
}
|
||||||
@ -695,7 +695,7 @@ class MySplitter {
|
|||||||
对象的`Symbol.iterator`属性,指向该对象的默认遍历器方法。
|
对象的`Symbol.iterator`属性,指向该对象的默认遍历器方法。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var myIterable = {};
|
const myIterable = {};
|
||||||
myIterable[Symbol.iterator] = function* () {
|
myIterable[Symbol.iterator] = function* () {
|
||||||
yield 1;
|
yield 1;
|
||||||
yield 2;
|
yield 2;
|
||||||
@ -776,7 +776,7 @@ class Collection {
|
|||||||
return 'xxx';
|
return 'xxx';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var x = new Collection();
|
let x = new Collection();
|
||||||
Object.prototype.toString.call(x) // "[object xxx]"
|
Object.prototype.toString.call(x) // "[object xxx]"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user