Skip to content

Commit 9ad229c

Browse files
committed
feat: update articles
1 parent de57ffb commit 9ad229c

7 files changed

Lines changed: 233 additions & 218 deletions

File tree

‎.meta/SUMMARY.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -318,8 +318,8 @@
318318
- [调用与堆栈](../JavaScript/V8 引擎/运行时/调用与堆栈.md)
319319
- [元编程](../JavaScript/元编程/README.md)
320320
- [Proxy](../JavaScript/元编程/Proxy.md)
321-
- [属性监听与数据绑定](../JavaScript/元编程/属性监听与数据绑定.md)
322-
- [装饰器](../JavaScript/元编程/装饰器.md)
321+
- [Reflect](../JavaScript/元编程/Reflect.md)
322+
- [数据绑定](../JavaScript/元编程/数据绑定.md)
323323
- [函数](../JavaScript/函数/README.md)
324324
- [函数声明与闭包](../JavaScript/函数/函数声明与闭包.md)
325325
- [函数调用与 this 绑定](../JavaScript/函数/函数调用与 this 绑定.md)

‎JavaScript/TypeScript/类型使用/Decorator.md‎

Lines changed: 0 additions & 147 deletions
Original file line numberDiff line numberDiff line change
@@ -156,150 +156,3 @@ p.test('Hello Jony');
156156
- target: 类本身
157157
- key:该参数所在的函数的函数名
158158
- index: 该参数在函数参数列表中的索引值
159-
160-
# 注解与元数据操作
161-
162-
所谓注解的定义就是:为相应的类附加元数据支持。所谓元数据可以简单的解释,就是修饰数据的数据,比如一个人有 name,age 等数据属性,那么 name 和 age 这些字段就是为了修饰数据的数据,可以简单的称为元数据。通过注解添加元数据,然后在装饰器中获取这些元数据,完成对类、类的方法等等的修改,可以在装饰器中添加元数据的支持,比如可以可以在装饰器工厂函数以及装饰器函数中添加元数据支持等。
163-
164-
## 注解使用
165-
166-
Reflect Metadata 是 ES7 的一个提案,它主要用来在声明的时候添加和读取元数据。Reflect Metadata 的 API 可以用于类或者类的属性上,如:
167-
168-
```ts
169-
function metadata(
170-
metadataKey: any,
171-
metadataValue: any
172-
): {
173-
(target: Function): void;
174-
(target: Object, propertyKey: string | symbol): void;
175-
};
176-
```
177-
178-
Reflect.metadata 当作 Decorator 使用,当修饰类时,在类上添加元数据,当修饰类属性时,在类原型的属性上添加元数据,如:
179-
180-
```ts
181-
@Reflect.metadata('inClass', 'A')
182-
class Test {
183-
@Reflect.metadata('inMethod', 'B')
184-
public hello(): string {
185-
return 'hello world';
186-
}
187-
}
188-
189-
console.log(Reflect.getMetadata('inClass', Test)); // 'A'
190-
console.log(Reflect.getMetadata('inMethod', new Test(), 'hello')); // 'B'
191-
```
192-
193-
譬如在 vue-property-decorator 6.1 及其以下版本中,通过使用 Reflect.getMetadata API,Prop Decorator 能获取属性类型传至 Vue,简要代码如下:
194-
195-
```ts
196-
function Prop(): PropertyDecorator {
197-
return (target, key: string) => {
198-
const type = Reflect.getMetadata('design:type', target, key);
199-
console.log(`${key} type: ${type.name}`);
200-
// other...
201-
};
202-
}
203-
204-
class SomeClass {
205-
@Prop()
206-
public Aprop!: string;
207-
}
208-
```
209-
210-
## 自定义 metadataKey
211-
212-
除能获取类型信息外,常用于自定义 metadataKey,并在合适的时机获取它的值,示例如下:
213-
214-
```ts
215-
function classDecorator(): ClassDecorator {
216-
return target => {
217-
// 在类上定义元数据,key 为 `classMetaData`,value 为 `a`
218-
Reflect.defineMetadata('classMetaData', 'a', target);
219-
};
220-
}
221-
222-
function methodDecorator(): MethodDecorator {
223-
return (target, key, descriptor) => {
224-
// 在类的原型属性 'someMethod' 上定义元数据,key 为 `methodMetaData`,value 为 `b`
225-
Reflect.defineMetadata('methodMetaData', 'b', target, key);
226-
};
227-
}
228-
229-
@classDecorator()
230-
class SomeClass {
231-
@methodDecorator()
232-
someMethod() {}
233-
}
234-
235-
Reflect.getMetadata('classMetaData', SomeClass); // 'a'
236-
Reflect.getMetadata('methodMetaData', new SomeClass(), 'someMethod'); // 'b'
237-
```
238-
239-
## 案例:Format
240-
241-
可以通过 reflect-metadata 包来实现对于元数据的操作。首先我们来看 reflect-metadata 的使用,首先定义使用元数据的函数:
242-
243-
```ts
244-
const formatMetadataKey = Symbol('format');
245-
246-
function format(formatString: string) {
247-
return Reflect.metadata(formatMetadataKey, formatString);
248-
}
249-
250-
function getFormat(target: any, propertyKey: string) {
251-
return Reflect.getMetadata(formatMetadataKey, target, propertyKey);
252-
}
253-
```
254-
255-
这里的 format 可以作为装饰器函数的工厂函数,因为 format 函数返回的是一个装饰器函数,上述的方法定义了元数据 `Sysmbol("format")`,用 Sysmbol 的原因是为了防止元数据中的字段重复,而 format 定义了取元数据中相应字段的功能。接着我们来在类中使用相应的元数据:
256-
257-
```ts
258-
class Greeter {
259-
@format('Hello, %s')
260-
name: string;
261-
262-
constructor(name: string) {
263-
this.name = message;
264-
}
265-
sayHello() {
266-
let formatString = getFormat(this, 'name');
267-
return formatString.replace('%s', this.name);
268-
}
269-
}
270-
271-
const g = new Greeter('Jony');
272-
console.log(g.sayHello());
273-
```
274-
275-
在上述中,我们在 name 属性的装饰器工厂函数,执行`@Format("Hello, %s")`,返回一个装饰器函数,且该装饰器函数修饰了 Greeter 类的 name 属性,将“name”属性的值写入为"Hello, %s"。然后再 sayHello 方法中,通过 getFormat(this,"name") 取到 formatString 为“Hello,%s”.
276-
277-
## 案例:Angular 2 DI
278-
279-
```ts
280-
type Constructor<T = any> = new (...args: any[]) => T;
281-
282-
const Injectable = (): ClassDecorator => target => {};
283-
284-
class OtherService {
285-
a = 1;
286-
}
287-
288-
@Injectable()
289-
class TestService {
290-
constructor(public readonly otherService: OtherService) {}
291-
292-
testMethod() {
293-
console.log(this.otherService.a);
294-
}
295-
}
296-
297-
const Factory = <T>(target: Constructor<T>): T => {
298-
// 获取所有注入的服务
299-
const providers = Reflect.getMetadata('design:paramtypes', target); // [OtherService]
300-
const args = providers.map((provider: Constructor) => new provider());
301-
return new target(...args);
302-
};
303-
304-
Factory(TestService).testMethod(); // 1
305-
```

‎JavaScript/元编程/Proxy.md‎

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -26,30 +26,7 @@ const proxy = new Proxy(
2626
// proxy.whatever => null
2727
```
2828

29-
# Reflect
30-
31-
```js
32-
const target = {
33-
get foo() {
34-
return this.bar;
35-
},
36-
bar: 3
37-
};
38-
39-
const handler = {
40-
get(target, propertyKey, receiver) {
41-
if (propertyKey === 'bar') return 2;
42-
43-
console.log(Reflect.get(target, propertyKey, receiver)); // this in foo getter references Proxy instance; logs 2
44-
console.log(target[propertyKey]); // this in foo getter references "target" - logs 3
45-
}
46-
};
47-
48-
const obj = new Proxy(target, handler);
49-
console.log(obj.bar); // 2
50-
```
51-
52-
# Proxy 典型应用
29+
# Proxy 案例
5330

5431
## 数据存储
5532

0 commit comments

Comments
 (0)