从C#到TypeScript - Reflect
总目录
从C#到TypeScript - Reflect
在C#里如果想只通过名字来生成类实例、获取属性或执行方法可以使用反射,反射是基于元数据,现在很多流行语言都支持元数据,以此来提供更多便利的功能。
ES6和TypeScript也有Reflect,不过因为JavaScript本身是解释型语言,很多操作如根据名字字符串获取属性,根据字符串执行函数这些原本就有支持,Reflect只是把这些操作归结到一起。
下面来通过例子来看下TS Reflect常见的用法。
Reflect Get/Set
定义如下:
Reflect.get(target, name, receiver);
Reflect.set(target, name, value, receiver);
看上去也很好理解,和C#很类似:
target:操作的对象
name:名字字符串
value:要赋的值
receiver:这个比较怪,因为类里可以有getter/setter属性,这两种操作可以在代码块里使用this
,如果要用Reflect操作的话,receiver就会代替这个this
。
Reflect的操作即使是类的private变量也能获取到。
class Test{
constructor(age: number){
this.age = age;
}
private _age: number;
get age(): number{
return this._age; // this 会被receiver代替
}
set age(value: number) {
this._age = value; // this 会被receiver代替
}
}
class Receiver{
_age: number = 2;
}
let t = new Test(1);
let r = new Receiver();
console.info(Reflect.get(t, "_age")); // 1, 获取t的_age值
console.info(Reflect.get(t, "age")); // 1, 获取t的age值
console.info(Reflect.set(t, "age", 3)); // true, 成功设置age值为3
console.info(Reflect.get(t, "age")); // 3, 再次获取t的age值
console.info(Reflect.get(t, "age", r)); // 2, 表面上是t的age,但实际上获取的是r的age
console.info(Reflect.set(t, "age", 3, r)); // true, 表面上是设置t的age, 实际上是设置r的age值为3
console.info(Reflect.get(r, "_age")); // 3, 直接获取r的_age
apply
上面是属性,还有方法,定义如下:
Reflect.apply(func, thisArg, args);
熟悉JS的朋友应该知道Function也有apply方法,fn.apply(obj, args)
,可以说是同样的效果。
如果要通过函数名来调用函数,可以这样做:
class Test{
add(a: number, b: number): number{
return a + b;
}
}
let t = new Test();
console.info(Reflect.apply(t["add"], t, [1, 2])); // 3, 虽然t["add"]可以直接执行,不过有时可能需要设置thisArg
define/delete property
define相比之前就真是简单把Object替换成了Reflect,delete和delete obj[name]
效果一样。
Reflect.defineProperty(target, propertyKey, attributes);
Reflect.deleteProperty(obj, name);
例子延用上面的对象t:
//define
Reflect.defineProperty(t, 'time', {
value: Date.now()
});
console.info(t.time); // 一串数字
//delete
let d = {time: 111};
console.info(d.time); // 111
Reflect.deleteProperty(d, 'time'); // 成功的话返回true,否则返回false
console.info(d.time); // undefined
可以看到define的参数attributes
是一个PropertyDescriptor对象,value
就是值,其他还有writable, enumerable, configurable
用来控制属性的权限。
对于delete,需要注意的是deleteProperty对class的属性是无效的。
has ownKeys
ownKeys
返回的是对象所有属性,包括不可枚举的,如Symbol之类。
has
用来判断对象是否有某个属性或方法,包括原型链上的。
class Test{
constructor(name: string){
this.name = name;
}
name: string;
flag: Symbol = Symbol('flag');
getName(): string{
return this.name;
}
}
let obj = new Test('123');
console.info(Reflect.has(obj, 'name')); // true
console.info(Reflect.has(obj, 'flag')); // true
console.info(Reflect.has(obj, 'get')); // true
console.info(Reflect.has(obj, 'toString')); // true
for(let p of Reflect.ownKeys(obj)){
console.info(p); // name, flag
}
其他
Reflect.construct(target,args)
实例化对象除了new之外,还可以用这个,有时候很有用,比如ORM框架里join的字段就可以在设置表时把关联的类型传给字段,使用时用该类型就可以创建出实例。
Reflect.getPrototypeOf(target) 和 Reflect.setPrototypeOf(target, prototype)
分别用于获取和设置对象的原型
Reflect.getOwnPropertyDescriptor(target, name)
设置对象属性的描述对象,如
configurable, writable, enumerable
。Reflect.isExtensible(target)
分别用于判断对象是否可扩展。
Reflect.preventExtensions(target)
让一个对象变为不可扩展
Reflect基本上就是把之前Object的方法和一些命令如delete
in
之类聚到一起,相信ES6之后用Reflect来做这些操作将成为主流。
从C#到TypeScript - Reflect的更多相关文章
- C# vs TypeScript - 高级类型
总目录 从C#到TypeScript - 类型 从C#到TypeScript - 高级类型 从C#到TypeScript - 变量 从C#到TypeScript - 接口 从C#到TypeScript ...
- 从C#到TypeScript - 变量
总目录 从C#到TypeScript - 类型 从C#到TypeScript - 高级类型 从C#到TypeScript - 变量 从C#到TypeScript - 接口 从C#到TypeScript ...
- 从C#到TypeScript - 接口
总目录 从C#到TypeScript - 类型 从C#到TypeScript - 高级类型 从C#到TypeScript - 变量 从C#到TypeScript - 接口 从C#到TypeScript ...
- 从C#到TypeScript - 类
总目录 从C#到TypeScript - 类型 从C#到TypeScript - 高级类型 从C#到TypeScript - 变量 从C#到TypeScript - 接口 从C#到TypeScript ...
- 从C#到TypeScript - function
总目录 从C#到TypeScript - 类型 从C#到TypeScript - 高级类型 从C#到TypeScript - 变量 从C#到TypeScript - 接口 从C#到TypeScript ...
- 从C#到TypeScript - 装饰器
总目录 从C#到TypeScript - 类型 从C#到TypeScript - 高级类型 从C#到TypeScript - 变量 从C#到TypeScript - 接口 从C#到TypeScript ...
- 从C#到TypeScript - Promise
总目录 从C#到TypeScript - 类型 从C#到TypeScript - 高级类型 从C#到TypeScript - 变量 从C#到TypeScript - 接口 从C#到TypeScript ...
- 从C#到TypeScript - Generator
总目录 从C#到TypeScript - 类型 从C#到TypeScript - 高级类型 从C#到TypeScript - 变量 从C#到TypeScript - 接口 从C#到TypeScript ...
- 从C#到TypeScript - async await
总目录 从C#到TypeScript - 类型 从C#到TypeScript - 高级类型 从C#到TypeScript - 变量 从C#到TypeScript - 接口 从C#到TypeScript ...
随机推荐
- 写了一个复杂的sql语句
$sp_sql = "select sp_ProductNo, sp_ProductName,sp_Standard,sp_Unit,sum(sp_Amount) as amount fro ...
- GOLang(第二篇 发起一个Http请求)
import ( "net/http" "net/url" ) //发送一个简单的get请求 func GetRequest { //联系使用 make(map ...
- html <select> 用JS控制默认选中项
<html> <head> <!--禁止页面缓存--><meta http-equiv="content-type" content=&q ...
- BZOJ 2038: [2009国家集训队]小Z的袜子(hose)&&莫对算法
这里跟曼哈顿最小生成树没有太大的关系. 时间复杂度证明: [BZOJ2038 小Z的袜子 AC代码] 排序方式: 第一关键字:l所在的块: 第二关键字:r从小到大. #include<cstdi ...
- apache的工作模式 和 最大连接数设置
经过测试 效果明显 (1)首选查看apache的工作模式 windows下的查看apache的工作模式命令:httpd -l 如果列出mod_win32.c,则表示是 win32.c 工作方式. 列出 ...
- 解析STL中典型的内存分配
1 vector 在C++中使用vector应该是非常频繁的,但是你是否知道vector在计算内存分配是如何么? 在c++中vector是非常类似数组,但是他比数组更加灵活,这就表现在他的大小是可以自 ...
- PHP Memcached 实现简单数据库缓存
Memcache常用方法 Memcache::add — 添加一个值,如果已经存在,则返回false Memcache::addServer — 添加一个可供使用的服务器地址 Memcache::cl ...
- Bootstrap入门(二十七)JS插件4:标签页
Bootstrap入门(二十七)JS插件4:标签页 标签页的切换可以带动内容的变化 首先我们引入CSS文件 <link href="bootstrap.min.css" re ...
- pytho查找斐波那契序列中的值
''' 实现斐波那契序列,查找其中第N个数的值 ''' def FeiBSequence(list,N): length=len(list); i=0; while i<length: if N ...
- js json和字符串的互转
json与字符串的互转: 下面格式两种只是针对引号有稍微的区别 var result = JSON.parse("{\"a\":\"擦擦\",\ ...