mirror of
https://github.com/ruanyf/es6tutorial.git
synced 2025-05-24 18:32:22 +00:00
Merge branch 'gh-pages' of github.com:ruanyf/es6tutorial into gh-pages
This commit is contained in:
commit
1764e48fdf
@ -14,7 +14,7 @@ function Point(x,y){
|
||||
|
||||
Point.prototype.toString = function () {
|
||||
return '(' + this.x + ', ' + this.y + ')';
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
上面这种写法跟传统的面向对象语言(比如C++和Java)差异很大,很容易让新学习这门语言的程序员感到困惑。
|
||||
@ -74,7 +74,7 @@ class Point {
|
||||
Point.prototype = {
|
||||
toString(){},
|
||||
toValue(){}
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
在类的实例上面调用方法,其实就是调用原型上的方法。
|
||||
@ -100,7 +100,7 @@ class Point {
|
||||
Object.assign(Point.prototype, {
|
||||
toString(){},
|
||||
toValue(){}
|
||||
})
|
||||
});
|
||||
```
|
||||
|
||||
`prototype`对象的`constructor`属性,直接指向“类”的本身,这与ES5的行为是一致的。
|
||||
@ -133,11 +133,11 @@ Object.getOwnPropertyNames(Point.prototype)
|
||||
```javascript
|
||||
var Point = function (x, y){
|
||||
// ...
|
||||
}
|
||||
};
|
||||
|
||||
Point.prototype.toString = function() {
|
||||
// ...
|
||||
}
|
||||
};
|
||||
|
||||
Object.keys(Point.prototype)
|
||||
// ["toString"]
|
||||
@ -585,7 +585,7 @@ var obj = {
|
||||
toString() {
|
||||
return "MyObject: " + super.toString();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
obj.toString(); // MyObject: [object Object]
|
||||
```
|
||||
|
@ -94,12 +94,12 @@ import { mixins } from './mixins'
|
||||
|
||||
const Foo = {
|
||||
foo() { console.log('foo') }
|
||||
}
|
||||
};
|
||||
|
||||
@mixins(Foo)
|
||||
class MyClass {}
|
||||
|
||||
let obj = new MyClass()
|
||||
let obj = new MyClass();
|
||||
obj.foo() // 'foo'
|
||||
```
|
||||
|
||||
@ -108,7 +108,7 @@ obj.foo() // 'foo'
|
||||
```javascript
|
||||
const Foo = {
|
||||
foo() { console.log('foo') }
|
||||
}
|
||||
};
|
||||
|
||||
class MyClass {}
|
||||
|
||||
@ -169,7 +169,7 @@ function nonenumerable(target, name, descriptor) {
|
||||
|
||||
下面的`@log`修饰器,可以起到输出日志的作用。
|
||||
|
||||
```bash
|
||||
```javascript
|
||||
class Math {
|
||||
@log
|
||||
add(a, b) {
|
||||
@ -498,7 +498,7 @@ export function mixins(...list) {
|
||||
然后,就可以使用上面这个修饰器,为类“混入”各种方法。
|
||||
|
||||
```javascript
|
||||
import { mixins } from './mixins'
|
||||
import { mixins } from './mixins';
|
||||
|
||||
const Foo = {
|
||||
foo() { console.log('foo') }
|
||||
@ -600,7 +600,7 @@ Trait也是一种修饰器,效果与Mixin类似,但是提供更多功能,
|
||||
下面采用[traits-decorator](https://github.com/CocktailJS/traits-decorator)这个第三方模块作为例子。这个模块提供的traits修饰器,不仅可以接受对象,还可以接受ES6类作为参数。
|
||||
|
||||
```javascript
|
||||
import { traits } from 'traits-decorator'
|
||||
import { traits } from 'traits-decorator';
|
||||
|
||||
class TFoo {
|
||||
foo() { console.log('foo') }
|
||||
@ -608,12 +608,12 @@ class TFoo {
|
||||
|
||||
const TBar = {
|
||||
bar() { console.log('bar') }
|
||||
}
|
||||
};
|
||||
|
||||
@traits(TFoo, TBar)
|
||||
class MyClass { }
|
||||
|
||||
let obj = new MyClass()
|
||||
let obj = new MyClass();
|
||||
obj.foo() // foo
|
||||
obj.bar() // bar
|
||||
```
|
||||
@ -623,7 +623,7 @@ obj.bar() // bar
|
||||
Trait不允许“混入”同名方法。
|
||||
|
||||
```javascript
|
||||
import {traits } from 'traits-decorator'
|
||||
import { traits } from 'traits-decorator';
|
||||
|
||||
class TFoo {
|
||||
foo() { console.log('foo') }
|
||||
@ -632,7 +632,7 @@ class TFoo {
|
||||
const TBar = {
|
||||
bar() { console.log('bar') },
|
||||
foo() { console.log('foo') }
|
||||
}
|
||||
};
|
||||
|
||||
@traits(TFoo, TBar)
|
||||
class MyClass { }
|
||||
@ -647,7 +647,7 @@ class MyClass { }
|
||||
一种解决方法是排除TBar的foo方法。
|
||||
|
||||
```javascript
|
||||
import { traits, excludes } from 'traits-decorator'
|
||||
import { traits, excludes } from 'traits-decorator';
|
||||
|
||||
class TFoo {
|
||||
foo() { console.log('foo') }
|
||||
@ -656,12 +656,12 @@ class TFoo {
|
||||
const TBar = {
|
||||
bar() { console.log('bar') },
|
||||
foo() { console.log('foo') }
|
||||
}
|
||||
};
|
||||
|
||||
@traits(TFoo, TBar::excludes('foo'))
|
||||
class MyClass { }
|
||||
|
||||
let obj = new MyClass()
|
||||
let obj = new MyClass();
|
||||
obj.foo() // foo
|
||||
obj.bar() // bar
|
||||
```
|
||||
@ -671,7 +671,7 @@ obj.bar() // bar
|
||||
另一种方法是为TBar的foo方法起一个别名。
|
||||
|
||||
```javascript
|
||||
import { traits, alias } from 'traits-decorator'
|
||||
import { traits, alias } from 'traits-decorator';
|
||||
|
||||
class TFoo {
|
||||
foo() { console.log('foo') }
|
||||
@ -680,12 +680,12 @@ class TFoo {
|
||||
const TBar = {
|
||||
bar() { console.log('bar') },
|
||||
foo() { console.log('foo') }
|
||||
}
|
||||
};
|
||||
|
||||
@traits(TFoo, TBar::alias({foo: 'aliasFoo'}))
|
||||
class MyClass { }
|
||||
|
||||
let obj = new MyClass()
|
||||
let obj = new MyClass();
|
||||
obj.foo() // foo
|
||||
obj.aliasFoo() // foo
|
||||
obj.bar() // bar
|
||||
|
@ -29,15 +29,15 @@ it.next() // { value: "a", done: false }
|
||||
it.next() // { value: "b", done: false }
|
||||
it.next() // { value: undefined, done: true }
|
||||
|
||||
function makeIterator(array){
|
||||
function makeIterator(array) {
|
||||
var nextIndex = 0;
|
||||
return {
|
||||
next: function(){
|
||||
next: function() {
|
||||
return nextIndex < array.length ?
|
||||
{value: array[nextIndex++], done: false} :
|
||||
{value: undefined, done: true};
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
@ -52,15 +52,15 @@ function makeIterator(array){
|
||||
对于遍历器对象来说,`done: false`和`value: undefined`属性都是可以省略的,因此上面的`makeIterator`函数可以简写成下面的形式。
|
||||
|
||||
```javascript
|
||||
function makeIterator(array){
|
||||
function makeIterator(array) {
|
||||
var nextIndex = 0;
|
||||
return {
|
||||
next: function(){
|
||||
next: function() {
|
||||
return nextIndex < array.length ?
|
||||
{value: array[nextIndex++]} :
|
||||
{done: true};
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
@ -74,14 +74,14 @@ it.next().value // '1'
|
||||
it.next().value // '2'
|
||||
// ...
|
||||
|
||||
function idMaker(){
|
||||
function idMaker() {
|
||||
var index = 0;
|
||||
|
||||
return {
|
||||
next: function(){
|
||||
next: function() {
|
||||
return {value: index++, done: false};
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
@ -166,31 +166,31 @@ for (var value of range(0, 3)) {
|
||||
下面是通过遍历器实现指针结构的例子。
|
||||
|
||||
```javascript
|
||||
function Obj(value){
|
||||
function Obj(value) {
|
||||
this.value = value;
|
||||
this.next = null;
|
||||
}
|
||||
|
||||
Obj.prototype[Symbol.iterator] = function(){
|
||||
Obj.prototype[Symbol.iterator] = function() {
|
||||
var iterator = {
|
||||
next: next
|
||||
};
|
||||
|
||||
var current = this;
|
||||
|
||||
function next(){
|
||||
if (current){
|
||||
function next() {
|
||||
if (current) {
|
||||
var value = current.value;
|
||||
var done = current.next === null;
|
||||
current = current.next;
|
||||
return {
|
||||
done: done,
|
||||
value: value
|
||||
}
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
done: true
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
return iterator;
|
||||
@ -204,7 +204,7 @@ one.next = two;
|
||||
two.next = three;
|
||||
|
||||
for (var i of one){
|
||||
console.log(i)
|
||||
console.log(i);
|
||||
}
|
||||
// 1
|
||||
// 2
|
||||
|
@ -91,7 +91,7 @@ export {firstName, lastName, year};
|
||||
export命令除了输出变量,还可以输出函数或类(class)。
|
||||
|
||||
```javascript
|
||||
export function multiply (x, y) {
|
||||
export function multiply(x, y) {
|
||||
return x * y;
|
||||
};
|
||||
```
|
||||
@ -350,7 +350,7 @@ import {crc32} from 'crc32';
|
||||
// modules.js
|
||||
function add(x, y) {
|
||||
return x * y;
|
||||
};
|
||||
}
|
||||
export {add as default};
|
||||
// 等同于
|
||||
// export default add;
|
||||
@ -402,7 +402,7 @@ export default 42;
|
||||
export default class { ... }
|
||||
|
||||
// main.js
|
||||
import MyClass from 'MyClass'
|
||||
import MyClass from 'MyClass';
|
||||
let o = new MyClass();
|
||||
```
|
||||
|
||||
@ -499,7 +499,7 @@ $ node main.js
|
||||
4
|
||||
```
|
||||
|
||||
ES6模块的运行机制与CommonJS不一样,它遇到模块加载命令`import`时,不会去执行模块,而是只生成一个动态的只读引用。等到真的需要用到时,再到模块里面去取值,换句话说,ES6的输入有点像Unix系统的”符号连接“,原始值变了,`import`输入的值也会跟着变。因此,ES6模块是动态引用,并且不会缓存值,模块里面的变量绑定其所在的模块。
|
||||
ES6模块的运行机制与CommonJS不一样,它遇到模块加载命令`import`时,不会去执行模块,而是只生成一个动态的只读引用。等到真的需要用到时,再到模块里面去取值,换句话说,ES6的输入有点像Unix系统的“符号连接”,原始值变了,`import`输入的值也会跟着变。因此,ES6模块是动态引用,并且不会缓存值,模块里面的变量绑定其所在的模块。
|
||||
|
||||
还是举上面的例子。
|
||||
|
||||
@ -545,7 +545,7 @@ baz
|
||||
|
||||
上面代码表明,ES6模块不会缓存运行结果,而是动态地去被加载的模块取值,并且变量总是绑定其所在的模块。
|
||||
|
||||
由于ES6输入的模块变量,只是一个”符号连接“,所以这个变量是只读的,对它进行重新赋值会报错。
|
||||
由于ES6输入的模块变量,只是一个“符号连接”,所以这个变量是只读的,对它进行重新赋值会报错。
|
||||
|
||||
```javascript
|
||||
// lib.js
|
||||
@ -571,7 +571,7 @@ function C() {
|
||||
};
|
||||
this.show = function () {
|
||||
console.log(this.sum);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export let c = new C();
|
||||
@ -616,7 +616,7 @@ var a = require('a');
|
||||
|
||||
通常,“循环加载”表示存在强耦合,如果处理不好,还可能导致递归加载,使得程序无法执行,因此应该避免出现。
|
||||
|
||||
但是实际上,这是很难避免的,尤其是依赖关系复杂的大项目,很容易出现`a`依赖b,`b`依赖`c`,`c`又依赖`a`这样的情况。这意味着,模块加载机制必须考虑“循环加载”的情况。
|
||||
但是实际上,这是很难避免的,尤其是依赖关系复杂的大项目,很容易出现`a`依赖`b`,`b`依赖`c`,`c`又依赖`a`这样的情况。这意味着,模块加载机制必须考虑“循环加载”的情况。
|
||||
|
||||
对于JavaScript语言来说,目前最常见的两种模块格式CommonJS和ES6,处理“循环加载”的方法是不一样的,返回的结果也不一样。
|
||||
|
||||
|
@ -146,7 +146,7 @@ var obj = {
|
||||
* m(){
|
||||
yield 'hello world';
|
||||
}
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
## 属性名表达式
|
||||
@ -233,9 +233,9 @@ var person = {
|
||||
console.log(this.name);
|
||||
},
|
||||
get firstName() {
|
||||
return "Nicholas"
|
||||
return "Nicholas";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
person.sayName.name // "sayName"
|
||||
person.firstName.name // "get firstName"
|
||||
@ -633,12 +633,12 @@ Reflect.ownKeys({ [Symbol()]:0, b:0, 10:0, 2:0, a:0 })
|
||||
// es6的写法
|
||||
var obj = {
|
||||
method: function() { ... }
|
||||
}
|
||||
};
|
||||
obj.__proto__ = someOtherObj;
|
||||
|
||||
// es5的写法
|
||||
var obj = Object.create(someOtherObj);
|
||||
obj.method = function() { ... }
|
||||
obj.method = function() { ... };
|
||||
```
|
||||
|
||||
该属性没有写入ES6的正文,而是写入了附录,原因是`__proto__`前后的双下划线,说明它本质上是一个内部属性,而不是一个正式的对外的API,只是由于浏览器广泛支持,才被加入了ES6。标准明确规定,只有浏览器必须部署这个属性,其他运行环境不一定需要部署,而且新的代码最好认为这个属性是不存在的。因此,无论从语义的角度,还是从兼容性的角度,都不要使用这个属性,而是使用下面的`Object.setPrototypeOf()`(写操作)、`Object.getPrototypeOf()`(读操作)、`Object.create()`(生成操作)代替。
|
||||
@ -662,7 +662,7 @@ Object.defineProperty(Object.prototype, '__proto__', {
|
||||
return undefined;
|
||||
}
|
||||
let status = Reflect.setPrototypeOf(this, proto);
|
||||
if (! status) {
|
||||
if (!status) {
|
||||
throw new TypeError();
|
||||
}
|
||||
},
|
||||
@ -756,7 +756,7 @@ Object.keys(obj)
|
||||
目前,ES7有一个[提案](https://github.com/tc39/proposal-object-values-entries),引入了跟`Object.keys`配套的`Object.values`和`Object.entries`。
|
||||
|
||||
```javascript
|
||||
let {keys, values, entries} = Object;
|
||||
let {keys, values, entries} = Object;
|
||||
let obj = { a: 1, b: 2, c: 3 };
|
||||
|
||||
for (let key of keys(obj)) {
|
||||
@ -943,9 +943,9 @@ var o = Object.create({ x: 1, y: 2 });
|
||||
o.z = 3;
|
||||
|
||||
let { x, ...{ y, z } } = o;
|
||||
x; // 1
|
||||
y; // undefined
|
||||
z; // 3
|
||||
x // 1
|
||||
y // undefined
|
||||
z // 3
|
||||
```
|
||||
|
||||
上面代码中,变量`x`是单纯的解构赋值,所以可以读取继承的属性;Rest解构赋值产生的变量`y`和`z`,只能读取对象自身的属性,所以只有变量`z`可以赋值成功。
|
||||
@ -1010,7 +1010,7 @@ let aWithOverrides = Object.assign({}, a, { x: 1, y: 2 });
|
||||
```javascript
|
||||
let newVersion = {
|
||||
...previousVersion,
|
||||
name: 'New Name', // Override the name property
|
||||
name: 'New Name' // Override the name property
|
||||
};
|
||||
```
|
||||
|
||||
@ -1074,7 +1074,7 @@ ES7有一个提案,提出了`Object.getOwnPropertyDescriptors`方法,返回
|
||||
```javascript
|
||||
const obj = {
|
||||
foo: 123,
|
||||
get bar() { return 'abc' },
|
||||
get bar() { return 'abc' }
|
||||
};
|
||||
|
||||
Object.getOwnPropertyDescriptors(obj)
|
||||
|
@ -35,7 +35,7 @@ obj.count = 1
|
||||
ES6原生提供Proxy构造函数,用来生成Proxy实例。
|
||||
|
||||
```javascript
|
||||
var proxy = new Proxy(target, handler)
|
||||
var proxy = new Proxy(target, handler);
|
||||
```
|
||||
|
||||
Proxy对象的所有用法,都是上面这种形式,不同的只是`handler`参数的写法。其中,`new Proxy()`表示生成一个Proxy实例,target参数表示所要拦截的目标对象,`handler`参数也是一个对象,用来定制拦截行为。
|
||||
@ -73,7 +73,7 @@ target.a // "b"
|
||||
一个技巧是将Proxy对象,设置到`object.proxy`属性,从而可以在`object`对象上调用。
|
||||
|
||||
```javascript
|
||||
var object = { proxy: new Proxy(target, handler) }
|
||||
var object = { proxy: new Proxy(target, handler) };
|
||||
```
|
||||
|
||||
Proxy实例也可以作为其他对象的原型对象。
|
||||
@ -97,14 +97,14 @@ obj.time // 35
|
||||
var handler = {
|
||||
get: function(target, name) {
|
||||
if (name === 'prototype') return Object.prototype;
|
||||
return 'Hello, '+ name;
|
||||
return 'Hello, ' + name;
|
||||
},
|
||||
apply: function(target, thisBinding, args) { return args[0]; },
|
||||
construct: function(target, args) { return args[1]; }
|
||||
};
|
||||
|
||||
var fproxy = new Proxy(function(x,y) {
|
||||
return x+y;
|
||||
var fproxy = new Proxy(function(x, y) {
|
||||
return x + y;
|
||||
}, handler);
|
||||
|
||||
fproxy(1,2); // 1
|
||||
@ -279,19 +279,6 @@ pipe(3).double.pow.reverseInt.get; // 63
|
||||
下面的例子则是利用`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) {
|
||||
@ -309,6 +296,19 @@ const dom = new Proxy({}, {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
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);
|
||||
```
|
||||
|
||||
### set()
|
||||
@ -357,7 +357,7 @@ var handler = {
|
||||
invariant(key, 'set');
|
||||
return true;
|
||||
}
|
||||
}
|
||||
};
|
||||
function invariant (key, action) {
|
||||
if (key[0] === '_') {
|
||||
throw new Error(`Invalid attempt to ${action} private "${key}" property`);
|
||||
@ -382,7 +382,7 @@ var handler = {
|
||||
apply (target, ctx, args) {
|
||||
return Reflect.apply(...arguments);
|
||||
}
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
`apply`方法可以接受三个参数,分别是目标对象、目标对象的上下文对象(`this`)和目标对象的参数数组。
|
||||
@ -461,7 +461,7 @@ var p = new Proxy(obj, {
|
||||
}
|
||||
});
|
||||
|
||||
"a" in p; // TypeError is thrown
|
||||
"a" in p // TypeError is thrown
|
||||
```
|
||||
|
||||
上面代码中,`obj`对象禁止扩展,结果使用`has`拦截就会报错。
|
||||
@ -475,7 +475,7 @@ var handler = {
|
||||
construct (target, args) {
|
||||
return new target(...args);
|
||||
}
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
下面是一个例子。
|
||||
@ -515,15 +515,15 @@ var handler = {
|
||||
invariant(key, 'delete');
|
||||
return true;
|
||||
}
|
||||
}
|
||||
};
|
||||
function invariant (key, action) {
|
||||
if (key[0] === '_') {
|
||||
throw new Error(`Invalid attempt to ${action} private "${key}" property`);
|
||||
}
|
||||
}
|
||||
|
||||
var target = { _prop: 'foo' }
|
||||
var proxy = new Proxy(target, handler)
|
||||
var target = { _prop: 'foo' };
|
||||
var proxy = new Proxy(target, handler);
|
||||
delete proxy._prop
|
||||
// Error: Invalid attempt to delete private "_prop" property
|
||||
```
|
||||
@ -537,11 +537,11 @@ delete proxy._prop
|
||||
```javascript
|
||||
var handler = {
|
||||
defineProperty (target, key, descriptor) {
|
||||
return false
|
||||
return false;
|
||||
}
|
||||
}
|
||||
var target = {}
|
||||
var proxy = new Proxy(target, handler)
|
||||
};
|
||||
var target = {};
|
||||
var proxy = new Proxy(target, handler);
|
||||
proxy.foo = 'bar'
|
||||
// TypeError: proxy defineProperty handler returned false for property '"foo"'
|
||||
```
|
||||
@ -557,9 +557,9 @@ var handler = {
|
||||
enumerate (target) {
|
||||
return Object.keys(target).filter(key => key[0] !== '_')[Symbol.iterator]();
|
||||
}
|
||||
}
|
||||
var target = { prop: 'foo', _bar: 'baz', _prop: 'foo' }
|
||||
var proxy = new Proxy(target, handler)
|
||||
};
|
||||
var target = { prop: 'foo', _bar: 'baz', _prop: 'foo' };
|
||||
var proxy = new Proxy(target, handler);
|
||||
for (let key in proxy) {
|
||||
console.log(key);
|
||||
// "prop"
|
||||
@ -607,11 +607,11 @@ for (var x in p) {} // 报错
|
||||
var handler = {
|
||||
getOwnPropertyDescriptor (target, key) {
|
||||
if (key[0] === '_') {
|
||||
return
|
||||
return;
|
||||
}
|
||||
return Object.getOwnPropertyDescriptor(target, key)
|
||||
return Object.getOwnPropertyDescriptor(target, key);
|
||||
}
|
||||
}
|
||||
};
|
||||
var target = { _foo: 'bar', baz: 'tar' };
|
||||
var proxy = new Proxy(target, handler);
|
||||
Object.getOwnPropertyDescriptor(proxy, 'wat')
|
||||
@ -682,7 +682,7 @@ var p = new Proxy({}, {
|
||||
}
|
||||
});
|
||||
|
||||
Object.isExtensible(p); // 报错
|
||||
Object.isExtensible(p) // 报错
|
||||
```
|
||||
|
||||
### ownKeys()
|
||||
@ -732,7 +732,7 @@ for (let key of Object.keys(proxy)) {
|
||||
|
||||
`preventExtensions`方法拦截`Object.preventExtensions()`。该方法必须返回一个布尔值。
|
||||
|
||||
这个方法有一个限制,只有当`Object.isExtensible(proxy)`为`false`(即不可扩展)时,`proxy.preventExtensions`才能返回true,否则会报错。
|
||||
这个方法有一个限制,只有当`Object.isExtensible(proxy)`为`false`(即不可扩展)时,`proxy.preventExtensions`才能返回`true`,否则会报错。
|
||||
|
||||
```javascript
|
||||
var p = new Proxy({}, {
|
||||
@ -741,7 +741,7 @@ var p = new Proxy({}, {
|
||||
}
|
||||
});
|
||||
|
||||
Object.preventExtensions(p); // 报错
|
||||
Object.preventExtensions(p) // 报错
|
||||
```
|
||||
|
||||
上面代码中,`proxy.preventExtensions`方法返回`true`,但这时`Object.isExtensible(proxy)`会返回`true`,因此报错。
|
||||
@ -773,7 +773,7 @@ var handler = {
|
||||
setPrototypeOf (target, proto) {
|
||||
throw new Error('Changing the prototype is forbidden');
|
||||
}
|
||||
}
|
||||
};
|
||||
var proto = {};
|
||||
var target = function () {};
|
||||
var proxy = new Proxy(target, handler);
|
||||
@ -915,7 +915,7 @@ Reflect.apply(Math.floor, undefined, [1.75]) // 1
|
||||
var obj = {
|
||||
get foo() { return this.bar(); },
|
||||
bar: function() { ... }
|
||||
}
|
||||
};
|
||||
|
||||
// 下面语句会让 this.bar()
|
||||
// 变成调用 wrapper.bar()
|
||||
|
@ -11,7 +11,7 @@ Set本身是一个构造函数,用来生成Set数据结构。
|
||||
```javascript
|
||||
var s = new Set();
|
||||
|
||||
[2, 3, 5, 4, 5, 2, 2].map(x => s.add(x))
|
||||
[2, 3, 5, 4, 5, 2, 2].map(x => s.add(x));
|
||||
|
||||
for (let i of s) {
|
||||
console.log(i);
|
||||
@ -25,7 +25,7 @@ Set函数可以接受一个数组(或类似数组的对象)作为参数,
|
||||
|
||||
```javascript
|
||||
// 例一
|
||||
var set = new Set([1, 2, 3, 4, 4])
|
||||
var set = new Set([1, 2, 3, 4, 4]);
|
||||
[...set]
|
||||
// [1, 2, 3, 4]
|
||||
|
||||
@ -35,14 +35,14 @@ items.size // 5
|
||||
|
||||
// 例三
|
||||
function divs () {
|
||||
return [...document.querySelectorAll('div')]
|
||||
return [...document.querySelectorAll('div')];
|
||||
}
|
||||
|
||||
var set = new Set(divs())
|
||||
var set = new Set(divs());
|
||||
set.size // 56
|
||||
|
||||
// 类似于
|
||||
divs().forEach(div => set.add(div))
|
||||
divs().forEach(div => set.add(div));
|
||||
set.size // 56
|
||||
```
|
||||
|
||||
@ -73,10 +73,10 @@ set // Set {NaN}
|
||||
```javascript
|
||||
let set = new Set();
|
||||
|
||||
set.add({})
|
||||
set.add({});
|
||||
set.size // 1
|
||||
|
||||
set.add({})
|
||||
set.add({});
|
||||
set.size // 2
|
||||
```
|
||||
|
||||
@ -376,7 +376,7 @@ class Foo {
|
||||
}
|
||||
method () {
|
||||
if (!foos.has(this)) {
|
||||
throw new TypeError('Foo.prototype.method 只能在Foo的实例上调用!')
|
||||
throw new TypeError('Foo.prototype.method 只能在Foo的实例上调用!');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -154,7 +154,7 @@ Symbol类型还可以用于定义一组常量,保证这组常量的值都是
|
||||
log.levels = {
|
||||
DEBUG: Symbol('debug'),
|
||||
INFO: Symbol('info'),
|
||||
WARN: Symbol('warn'),
|
||||
WARN: Symbol('warn')
|
||||
};
|
||||
log(log.levels.DEBUG, 'debug message');
|
||||
log(log.levels.INFO, 'info message');
|
||||
|
Loading…
x
Reference in New Issue
Block a user