Object方法与Reflect
栏目: JavaScript · 发布时间: 6年前
内容简介:本篇旨在梳理对象静态方法,与此同时采用对比的方式介绍Reflect接口,在梳理过程中当做学习笔记,如果对于读者有帮助就更好了。对象模型方法包括获取属性描述及定义属性注意:Object.defineProperty || Reflect.defineProperty || Object.defineProperties 定义属性时,属性描述没有设置为true的话,全部
本篇旨在梳理对象静态方法,与此同时采用对比的方式介绍Reflect接口,在梳理过程中当做学习笔记,如果对于读者有帮助就更好了。
一、Object静态方法与对应Reflect
1、遍历对象属性方法
- for...in:非静态方法,此处为展示继承效果,返回非Symbol类的继承和自身属性。
- Object.keys(obj):返回一个数组,数组成员为obj自身(非继承)、可枚举、非Symbol类型属性名。
- Object.values(obj):返回自身(非继承)、可枚举、非Symbol类型属性的值。
- Object.entries(obj):返回自身(非继承)、可枚举、非Symbol类型属性的键值对数组。
- Object.fromEntries(obj):Object.entries方法的逆操作,将一个键值对数组转换为对象。
- Object.getOwnPropertyNames(obj):返回一个数组,数组成员为obj自身属性(非继承)、非Symbol类型属性名,与Object.keys()的区别在于返回数组成员包括不可枚举属性。
- Object.getOwnPropertySymbols(obj):返回一个数组,数组成员为obj自身所有的Symbol类型属性名。
- Reflect.ownKeys(obj):返回一个数组,数组成员为obj自身所有的属性,是Object.getOwnPropertyNames(obj)与Object.getOwnPropertySymbols(obj)结果集合。
// 定义三个Symbol类型属性名 let [s1, s2, s3] = [Symbol(), Symbol(), Symbol()] let parent = { k1: 'a', k2: 'b', [s1]: 's1', f1: function() {} } let child = {} //child继承parent Object.setPrototypeOf(child, parent) //为child对象添加属性及描述 Object.defineProperties(child, { k3: { value: 'c', enumerable: true }, k4: { value: 'd', enumerable: false }, [s2]: { value: 's2', enumerable: true }, [s3]: { value: 's3', enumerable: false }, f2: { value: function() {}, enumerable: true } }) //arr承载for...in 的属性名 let arr = [] for (let key in child) { arr.push(key) } arr // ["k3", "f2", "k1", "k2", "f1"] Object.keys(child) //["k3", "f2"] Object.values(child)//["c", ƒ] Object.entries(child)//[["k3", "c"],["f2", ƒ]] Object.getOwnPropertyNames(child) //["k3", "k4", "f2"] Object.getOwnPropertySymbols(child) // [Symbol(), Symbol()] Reflect.ownKeys(child) // ["k3", "k4", "f2", Symbol(), Symbol()] 复制代码
2、对象模型方法
对象模型方法包括获取属性描述及定义属性
- Object.getOwnPropertyDescriptor(obj , propertyKey):返回一个对象,对象为obj属性propertyKey描述。
- Reflect.getOwnPropertyDescriptor(obj , propertyKey):返回一个对象,对象为obj属性propertyKey描述。 将来会替代Object.getOwnPropertyDescriptor(obj,propertykey)。
- Object.getOwnPropertyDescriptors(obj):返回一个对象,对象obj的全部属性的描述。
- Object.defineProperty(obj , propertyKey , attributes):在obj对象中添加属性和属性描述。
- Reflect.defineProperty(obj , propertyKey , attributes):用法同Object.defineProperty(obj,propertykey,attributes), 将来会替代Object.defineProperty(obj,propertykey,attributes)。
- Object.defineProperties(obj , propertyKeys , attributes)通过描述对象,定义多个属性。
注意:Object.defineProperty || Reflect.defineProperty || Object.defineProperties 定义属性时,属性描述没有设置为true的话,全部 默认为false 。
let obj = {} //添加属性描述 Object.defineProperty(obj, 'a', { value: "a", enumnerabl: true }) //添加属性描述 Reflect.defineProperty(obj, 'b', { value: "b", writable: true }) //添加属性描述 Object.defineProperties(obj, { 'c': { value: 'c', configurable: true } }) Object.getOwnPropertyDescriptor(obj, 'a') //{value: "a", writable: false, enumerable: false, configurable: false} Reflect.getOwnPropertyDescriptor(obj, 'a') //{value: "a", writable: false, enumerable: false, configurable: false} Object.getOwnPropertyDescriptors(obj) /*a: {value: "a", writable: false, enumerable: false, configurable: false} b: {value: "b", writable: true, enumerable: false, configurable: false} c: {value: "c", writable: false, enumerable: false, configurable: true}*/复制代码
3、控制对象方法
扩展--密封--冻结: 对象控制程度依次增强 。
- Object.isExtensible(obj):判断对象是否可扩展,返回布尔值。
- Object.preventExtensions(obj):阻止对象obj扩展, 其实就是阻止新增属性,不影响修改已有属性及删除属性。
let obj = { a: 'a', b: 'b' } Object.preventExtensions(obj) Object.isExtensible(obj) //false复制代码
- Reflect.preventExtensions(obj):作用同Object.preventExtensions(obj)。
- Reflect.isExtensible (obj):作用同Object.isExtensible(obj), 区别 在于如果参数不是对象,Object.isExtensible会返回false,因为 非对象本是不可扩展 的,而Reflect.isExtensible会报错。
let obj = { a: 'a', b: 'b' } Reflect.preventExtensions(obj) Reflect.isExtensible(obj) //false 复制代码
- Object.seal(obj):密封对象obj。 除了修改已有属性的值 ,其他操作(修改已有属性描述、新增属性、删除属性)均不允许。
- Object.isSealed(obj):判断对象是否密封,返回布尔值。
let obj = { a: 'a', b: 'b' } Object.seal(obj) Object.isSealed(obj) //true复制代码
- Object.freeze(obj):冻结对象,对象一旦冻结, 属性的操作全部不允许 ,换句话说,对象冻结,对象永不可变。
- Object.isFrozen(obj):判断一个对象是否被冻结,返回一个布尔值。
let obj = { a: 'a', b: 'b' } Object.freeze(obj) Object.isFrozen(obj) //true复制代码
4、原型链方法
该节主要介绍实例对象之间的继承以及查看实例对象继承源。
- Object.create(proto [,propertiesObject]):使用指定的对象及其属性创建一个新对象。 Object.create生成的对象,动态继承原型对象 。
proto:新创建对象的原型对象,可以为null。
propertiesObject:一个或多个属性的描述。
经常见到有文章用new命令与Object.create方法比较,个人理解new命令是创建够构造函数的实例(Object本身就是个函数,可以当成构造函数使用),而如何 从一个实例对象生成另外一个实例对象 呢,这个时候Object.create就应运而生了。
const parent = { print: function() { console.log("I am from parent") } } const child = Object.create(parent) child.print() //I am from parent 复制代码
class parent { constructor(x = 1, y = 2) { this.x = x; this.y = y } multi() { console.log(this.x * this.y) } } let child = new parent(3, 4) let grandson = Object.create(child) grandson.multi() //12复制代码
- Object.setPrototypeOf(obj , proto):设置该对象的原型。使用obj.__proto__设置为proto,返回参数对象obj本身。
个人理解:Object.create()与Object.setPrototypeOf()两种方法的差别在于:Object.create()利用原型对象生成一个新对象,而Object.setPrototype()是为已有对象设置原型对象,在实际使用时,在不添加属性集描述情况下,两者没有差别。
- Reflect.setPrototypeOf(obj , proto): 返回表示是否成功的布尔值 ,与Object.setPrototypeOf(obj , proto)对应,个人认为将来Reflect.setPrototypeOf会替代Object.setPrototypeOf。
- Object.getPropertypeOf(obj):读取对象的__proto__属性,返回对象obj的原型对象。
- Reflect.getPrototypeOf(obj):与Object.getPrototypeOf(obj)对应,个人认为将来Reflect.getPrototypeOf会替代Object.getPrototypeOf。
区别:如果参数不是对象,Object.getPrototypeOf会将这个参数转为对象,然后再运行,而Reflect.getPrototypeOf会报错。
let a = { a: 'a' } let b = Object.setPrototypeOf({}, a) let c = Object.create(a) //注意Reflect.setPrototypeOf(obj,proto)的使用 let d = {} Reflect.setPrototypeOf(d, a) Object.getPrototypeOf(b) //{a: "a"} Reflect.getPrototypeOf(c) //{a: "a"} Reflect.getPrototypeOf(d) //{a: "a"}复制代码
- Object.assign(target , source1 , ...):用于将所有可枚举属性的值从一个或多个源对象复制到目标对象,返回目标对象。
Object.assign方法复制的属性有几个点:非继承、属性可枚举、同名覆盖(前提是可枚举)、Symbol类属性唯一,最重要的是只能 浅拷贝 。
let [s1, s2, s3] = [Symbol(), Symbol(), Symbol()] let parent = { parent: 'parent', s1: 's1' } let child = Object.create(parent, { c1: { value: 'c1', enumbrable: true }, c2: { value: 'c2', enumerable: false }, c3: { value: 'c3', enumerable: true }, [s2]: { value: 's2', enumerable: true }, [s3]: { value: 's3', enumerable: true } }) let c_assign = { c1: 'ca1', c2: 'ca2', [s2]: 'sa2', } Object.assign(c_assign, child, { d: 'd' }) c_assign //{c1: "ca1", c2: "ca2", c3: "c3", d: "d", Symbol(): "s2", Symbol(): "s3"}复制代码
二、Reflect实例对象方法
1、Reflect操作实例对象属性方法
- Reflect.has(obj , properKey):判断实例对象obj是否存在属性propertyKey,返回布尔值。
- Reflect.deleteProperty(obj , propertyKey):等同于delete obj[propertyKey],删除实例对象的属性,返回布尔值。
- Reflect.get(target , name [,receiver]):获取属性值的方法。
不设置receiver时,获取target对象的属性。如果target不是对象,报错。
receiver的功能可以理解为数据源,将数据源中的属性值作用在target对象部署读取函数的属性上。target对象中存在两个关键词 get和this 。
let o1 = { a: 1, b: 2, get sum() { return this.a + this.b } } let o2 = { a: 3, b: 4 } Reflect.get(o1, 'a') //1 Reflect.get(o1, 'sum', o2) //7复制代码
- Reflect.set(target , propertyKey , value [,receiver]):设置实例对象target属性propertyKey值为value,如果设置receiver,则对于receiver中的属性进行设值。
如果属性propertyKey存在,则更改属性propertyKey值为value;如果属性不存在,则新增一个属性并赋值。
当receiver存在时,可以理解为使用目标对象target中设置赋值函数的属性propertyKey设置receiver中属性值为value。target对象中存在两个关键词 set和this 。
另外,receiver中属性在赋值函数中不存在时,为receiver对象新增一个属性,并赋值。
//展示效果 let o3 = { a: 1, set c(v) { this.a = v } } let o4 = { a: 0 } Reflect.set(o3, 'a', 2) //o3.a=2 Reflect.set(o3, 'b', 3) //o3.b=3 Reflect.set(o3, 'c', 5, o4) //o4.a=5、o3.a=2复制代码
let o3 = { a: 1, set c(v) { this.d = v } } let o4 = { a: 0 } Reflect.set(o3, 'c', 5, o4) //o4.d=5复制代码
//Reflect.set在Array上的使用 let arr = ['a', 'b', 'c'] Reflect.set(arr, 2, 'd') //arr=["a", "b", "d"] Reflect.set(arr, 4, 'd') //arr= ["a", "b", "d", empty, "d"] Reflect.set(arr, 'length', 2) //arr= ["a", "b"]复制代码
2、Reflect函数绑定方法
- Reflect.apply(fn , thisArg,args):指定的参数列表args向目标函数fn发起调用。
thisArg是函数fn调用时绑定的this对象。 args是调用时传递的类数组的对象参数列表
//为了区分教程上案例 const fn = function(v) { let arr = Reflect.ownKeys(this) return arr[v] } let obj = { a: 'a', b: 'b', c: 'c' } Reflect.apply(fn, obj, [1]) //'b'复制代码
3、Reflect调用构造函数方法
- Reflect.construct(target , args):与new操作符一样,来调用构造函数。
这个方法还有第三个参数,可选,暂时不涉及
function A(a) { this.b = a } let a = Reflect.construct(A, ['aa']) //a={b:'aa'}复制代码
三、后续
希望大家针对文中的内容多多指点,另外对于文章没有提到的方法大家提出来,我也会后续进行更改和补充,谢谢大家。
以上所述就是小编给大家介绍的《Object方法与Reflect》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 理解实例方法、类方法、静态方法
- 【MyBatis源码分析】insert方法、update方法、delete方法处理流程(上篇)
- 【MyBatis源码分析】insert方法、update方法、delete方法处理流程(上篇)
- java:方法覆盖与方法重载
- 静态方法、实例化方法与线程安全
- JS数组方法总览及遍历方法耗时统计
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。