前端学习(六十五) JavaScript-Reflection(javaScript)

反射机制的定义

通俗来讲,反射机制指的是程序在运行时能够获取自身的信息。

换一种说法

假设有一个对象obj,我们不知道他的内部结构和Api,这个时候我们通过某种机制获取了一个对象的内部结构这种机制就叫做反射

看个简单的例子:

            for(let a in window){
                console.log(a);
            }
            window.open('http://www.163.com')

这里的for in就是一个简单的反射,另外类似于Object.keys获取对象上的属性之类的方法都是称作反射

Reflect

Recflect是一个内置的对象,它提供拦截JavaScript操作的方法

  • Reflect没有构造函数,不能使用new运算符去新建,也不能将其作为一个函数去调用
  • Recflect的所有属性和方法都是静态的(类似Math对象)

为什么需要Reflect对象?

实现反射机制的方法重新归结在一起并简化操作,保持JS语意清晰和语法简单,如下示例

            let key1='id';
            let key2=Symbol.for('name')
            let obj={[key1]:1,[key2]:2}
            let keys=Object.getOwnPropertyNames(obj).concat(Object.getOwnPropertySymbols(obj))

            let keys2= Reflect.ownKeys(obj);

原来的方法必须两次获取获取对象的key值,而使用Reflect方法后,就直接一次获取了

另外,Reflect补充了一些Object对象没有的方法,比如Reflect.apply

还有,Reflect让Object操作都变成了函数行为,比如使用Reflect.has(obj,name)替换name in obj,这样代码的维护性更好

Reflect的方法

Reflect一共提供了13个静态方法

Reflect.apply()

对一个函数进行调用操作,同时可以传入一个数组作为调用参数

Reflect.apply(target,thisArgument,argumentsList)

target:目标函数

thisArgument:是target调用时绑定的字符对象

[,newTargert]:调用构造函数的数组

Reflect.construct()

对构造函数进行new操作,相当于执行new target(...args)。

Reflect.construct(target,argumentsList[,newTarget])

Reflect.construct(Date,[2018,1,1])    //输出data类型,也就是日期,Thu Feb 01 2018 00:00:00 GMT+0800 (中国标准时间)

Reflect.defineProper()

定义对象的一个属性

Reflect.defineProperty(target,property,attributes)

target:目标对象

property:要定义或修改的属性名称

attributes:属性描述

Reflect.deleteProperty()

删除对象的一个属性

Reflect.deleteProperty(target,propert)

target:目标对象

property:要删除的属性名称

Reflect.get()

查找并返回对象的属性值

Reflect.get(target,property[,receiver])

target:目标对象

property:属性名

receiver:(可选)如果遇到get,那么属性名就要去获取receiver中的属性名的值

             let c={
                 a:1,
                 b:2,
                 get c(){
                     return this.a+this.b
                 }
             }
             let d={
                 a:4,
                 b:4
             }
             console.log(Reflect.get(c,'a',d)); //1
             console.log(Reflect.get(c,'b',d)); //2
             console.log(Reflect.get(c,'c',d)); //8,如果没有参数d,那么获取到的值就是3

Reflect.set()

查找并返回对象的属性值

Reflect.set(target,property,value[,receiver])

target:目标对象

property:属性名

value:设置的值

receiver:(可选)如果遇到set,this将传给目标调用

Reflect.getOwnPropertyDescriptor()

查找并返回对象的属性描述符

Reflect.getOwnPropertyDescriptor(target,propertyKey)

target:目标对象

propertyKey:属性名称

Reflect.getPrototypeOf()

返回指定对象的原型,读取对象的__proto__属性

Reflect.getPrototypeOf(target)

target:目标对象

Reflect.setPrototypeOf()

设置指定对象的原型

Reflect.setPrototypeOf(target,prototype)

target:目标对象

prototype:设置需要的原型

Reflect.has()

判断obj是否有某个属性和in功能相同

Reflect.has(targert,prototype)

target:目标对象

prototype:属性名称

             let student={
                 a:'a'
             }
             //in写法
             console.log('a' in student);
             //has写法
             console.log(Reflect.has(student,'a'));

Reflect.isExtensible()

判断一个对象是否可扩展

Reflect.isExtensible(target)

target:目标对象

Reflect.preventExtensible()

让对象变为不可扩展

Reflect.preventExtensible(target)

target:目标对象

             let e={};
             console.log(Reflect.isExtensible(e));    //true
             Reflect.preventExtensions(e)    //设置为不可扩展
             console.log(Reflect.isExtensible(e));    //false
             e.name='aaa';    //设置无效
             console.log(e);    //空对象{}

Reflect.ownKeys()

返回一个包含所有自身属性(不包含继承属性)的数组

Reflect.ownKeys(target)

target:目标对象

             let f={};
             Object.defineProperty(f,"name",{
                 value:'123',
                 enumerable:true
             })
             console.log(Reflect.ownKeys(f));    //可枚举不可枚举的都可以查询到
             for(let g in f){
                 console.log(g);
                 
             }

Proxy

Proxy用于修改对象的某些默认行为,获取值,设置值等

语法

let p=new Proxy(target,handle);

target:用Proxy包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至是另一个代理)

handle:一个对象,其属性是当执行一个操作时定义代理的行为函数

Proxy.revoceable(target,handle)

创建的对象和new Proxy()一致

handle对象支持13个代理方法,如下

handle get

拦截对象属性值的获取

get(target,property,receiver)

target:目标对象

property:属性名

receiver:所操作的对象

             let students={
                 _key:'aaa',
                 name:"xiaoming"
             }
             let handle={
                 get:function(target,property,receiver){
                     if(property.startsWith('_')){
                         throw new Error("属性是私有的")
                     }
                     else{
                         return Reflect.get(target,property,receiver)
                     }
                 }
             }
             let p=new Proxy(students,handle);
            console.log(p.name);
            console.log(p._key);

示例就是保证以_开头的私有属性不会被访问到

handler set

拦截对象属性值的设置

set(target,property,value,receiver)

target:目标对象

property:属性名

value:属性值

receiver:所操作的对象

            let students1={
                 _key:'aaa',
                 name:"xiaoming"
             }
             let handle1={
                 set:function(target,property,value,receiver){
                     if(property.startsWith('_')){
                         throw new Error("属性是私有的")
                     }
                     else{
                         return Reflect.set(target,property,value,receiver)
                     }
                 }
             }
             let p1=new Proxy(students1,handle1);
             p1.name='小兰';
             p1._key="xiaolan"

handler deleteProperty

target:目标对象

property:属性名

拦截对象属性的删除

handler deleteProperty(target,property)

             let handle2={
                 deleteProperty:function(target,property){
                     if(property.startsWith('_')){
                         throw new Error("属性是私有的")
                     }
                     else{
                         return Reflect.deleteProperty(target,property)
                     }
                 }
             }
             let p2=new Proxy(students1,handle1);
             delete p2._key;

保证私有属性不被删除

hander getOwnpropertyDescirptor

拦截获取对象属性描述

hander getOwnpropertyDescirptor(target,property)

target:目标对象

property:属性名

handler defineProperty

拦截定义对象属性描述

handler defineProperty(target,property,descriptor)

target:目标对象

property:属性名

descriptor:属性描述

handler has

拦截判断对象属性是否存在,包括property in proxy和reflect.has,不包括Object.prototype.hasOwnProperty

handler has(target,property)

target:目标对象

property:属性名

handler ownKeys

拦截对象自身属性key值的读取操作,返回字符串或Symbol值数组

  • Object.getOwnPropertyNames()
  • Object.getOwnPropertySymbols()
  • Object.keys()
  • for in循环

ownKeys(target)

handler apply

拦截函数调用

apply(target,ctx,args)

handler construct

拦截构造函数调用

construc(target,args)

handler getPrototyperOf

拦截获取对象的原型

  • Object.prototype.__proto__
  • Object.prototype.isPrototypeOf()
  • Object.getPrototypeOf()
  • Reflect.getPrototypeOf()
  • instanceof

getPrototypeOf(target)

             let student1={};
             let handle3={
                 getPrototypeOf(target){
                     return student1;
                 }
             }
             let proxy1=new Proxy(student1,handle3)
             console.log(Object.getPrototypeOf(proxy1)=== student1);    //true

handler setPrototyperOf

拦截设置对象的原型

  • Object.prototype.__proto__
  • Object.setPrototypeOf()
  • Reflect.setPrototypeOf()

setPrototypeOf(target,proto)

target:目标对象

proto:具体的原型

handler  isExtensible

拦截对象是否可扩展

isExtensible(target)

target:目标对象

handler  preventExtensible

拦截对象的组织扩展方法

preventExtensible(target)

target:目标对象

猜你喜欢

转载自blog.csdn.net/zy21131437/article/details/81460001