Object方法与Reflect

栏目: JavaScript · 发布时间: 7年前

内容简介:本篇旨在梳理对象静态方法,与此同时采用对比的方式介绍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》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Agile Web Development with Rails 4

Agile Web Development with Rails 4

Sam Ruby、Dave Thomas、David Heinemeier Hansson / Pragmatic Bookshelf / 2013-10-11 / USD 43.95

Ruby on Rails helps you produce high-quality, beautiful-looking web applications quickly. You concentrate on creating the application, and Rails takes care of the details. Tens of thousands of deve......一起来看看 《Agile Web Development with Rails 4》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试