专栏首页技术/开源从C#到TypeScript - Reflect

从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来做这些操作将成为主流。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 从C#到TypeScript - 变量

    从C#到TypeScript - 变量 TypeScript的变量声明和ES6差不多,相比之前主要是多了let和const 为什么不用var 不管是TypeSc...

    用户1147588
  • 从C#到TypeScript - Proxy

    从C#到TypeScript - Proxy 我们知道在C#中要实现代理功能需要自己来实现代理类,并且每个类需要不同的代理类,使用起来不方便,虽然借助一些AOP...

    用户1147588
  • UWP开源项目 LLQNotifier 页面间通信利器(移植EventBus)

    前言 EventBus是一个Android版本的页面间通信库,这个库让页面间的通信变得十分容易且大幅降低了页面之间的耦合。小弟之前玩Android的时候就用得十...

    用户1147588
  • 本周AI热点回顾:wuhan2020登上Github热榜、五分之一作者将缺席AAAI2020

    近日,Github上一个名叫“wuhan2020”的项目登上了热榜,这是一个武汉新型冠状病毒防疫信息收集平台。项目前端网页:https://wuhan2020....

    用户1386409
  • DAY31:阅读global memory

    GPUS Lady
  • Flink系列——感性认识

    老板都是复制整个工厂的整体把控的, 一般不亲自动手,只需要管好 工厂的车间组长 就可以了。 JobManager 则是负责整个集群的资源管理与任务管理, ...

    solve
  • 阿里2018营收2502亿元,云计算业务增幅超100%

    5 月 4 日,阿里巴巴集团公布了 2018 财年第四季度(2018 年 1 月 1 日—3 月 31 日)的财报及 2018 财年业绩。

    AI科技大本营
  • 美团面试经历,贡献出来一起学习

    美团我是在拉勾网上投的简历,之前也投过一次,简历都没通过删选,后来让学姐帮我改了一下简历,重新投另一个部门,获得了面试机会。10月23日中午HR打电话过来预约了...

    用户1655470
  • 美团面试经历,贡献出来一起学习

      晚7点,因为想到下周一才面试,我刚准备出去打个羽毛球,北京的电话就来了。面试官各种抱歉,说开会拖延了。 1、自我介绍 说了很多遍了,很流畅捡重点介绍完。...

    用户2196435
  • [PYTHON]简单的文件增删改查处理

    快一个月木有更新了,在这段时间内,博主除了忙工作外,就一直在研究python编程,据圈内朋友闲聊,python应该是未来一个运维攻城狮除了shell以外必备的...

    py3study

扫码关注云+社区

领取腾讯云代金券