文章目录

  • 一、Object.defineProperty()
    • 1.1 什么意思?
    • 1.2 尝试一下
    • 1.3 调用
    • 1.4 语法
    • 1.5 描述
  • 二、descriptor 描述符
    • 2.1 configurable 可配置的
    • 2.2 enumerable 可枚举的
      • 2.2 补充 如何枚举 enumerable:false 的对象属性
    • 2.3 writable 可写的
    • 2.4 get 获取
    • 2.5 set 设置
    • 2.6 异常
    • 2.7 描述符默认值汇总
  • 三、案例
    • 3.1 自定义 set 和 get
      • 3.1.1 实现一个自存档类
      • 3.1.2 get总是返回相同的属性值
    • 3.2 继承属性时的一些注意事项
  • 四、Object.defineProperties()

一、Object.defineProperty()

Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象

更加具体的去描述或操作一个对象内部属性的操作性。

1.1 什么意思?

  • defineProperty 给对象定义属性
  • define 规定、定义
  • Property 属性 对象的key // Attribute

1.2 尝试一下

let obj = {}let newObj = Object.defineProperty(obj, 'a', {value: 1
})console.log(newObj === obj); // true
console.log('obj: ', obj);
console.log('newObj: ', newObj);

测试结果:

由此可知,确实给对象定义了一个新属性 => a=1,且返回的就是该对象( newObj 恒等于 obj )

1.3 调用

defineProperty是Object的静态方法,不能在普通对象上直接调用(没在原型链上),

function Star(){...}Star.sex = '男' // 静态成员
Star.sing = function (){ // 静态方法...
}

1.4 语法

语法 Object.difineProperty(obj,prop,descriptor)

obj:要定义的对象
prop:要定义或修改的属性名称
descriptor:定义或修改的操作符(五个)

1.5 描述

  • 该方法允许精确地添加或修改对象的属性
  • 通过赋值操作添加的普通属性可枚举的,在枚举对象属性时会被枚举到(for…in 或 Object.keys 方法)
  • 默认情况下,使用 Object.defineProperty() 添加的属性值不可修改(immutable)的。
  • 这个方法允许修改默认的额外选项(或配置

接下来我们进行测试:

let obj = {}
let newObj = Object.defineProperty(obj, 'a', {value: 1
})obj.a = 2 // 没变化,不可修改
delete obj.a // 没变化,不可删除for (let k in obj) {console.log(k, obj[k]);  // 没输出,不可枚举
}

测试结构:

控制台啥也没有,由此可知 我们通过 Object.defineProperty() 添加的属性有三个特点:

  • 不可修改
  • 不可删除
  • 不可枚举

二、descriptor 描述符

2.1 configurable 可配置的

configurable 可配置 able=>可能的,有能力的
configurable 特性表示对象的属性是否可以被删除,以及除 value 和 writable 特性外的其他特性是否可以被修改。

configurable :默认为 false。

let obj = {}
let newObj = Object.defineProperty(obj, 'a', {value: 1,configurable: true,
})
delete obj.a
console.log(obj); // {}

通过上述测试可知,当configurable为true时,我们就可以删除该属性了。

2.2 enumerable 可枚举的

enumerable默认为false

let obj = {}
let newObj = Object.defineProperty(obj, 'a', {value: 1,enumerable: true, // 可枚举的 Default:false
})
for (let k in obj) {console.log(k);
}


通过上述测试可知,当enumerable为true,可枚举该属性

2.2 补充 如何枚举 enumerable:false 的对象属性

需求:枚举对象obj的所有属性

let obj = {}
Object.defineProperty(obj, 'a', {value: 1,enumerable: false
})
Object.defineProperty(obj, 'b', {value: 2,enumerable: false
})

普通方法:

for (let k in obj) {console.log(k); // 空
}

进阶方法:

let keys = Object.getOwnPropertyNames(obj)
console.log(keys); // ["a", "b"]

Object.getOwnPropertyNames() 方法返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性但不包括Symbol值作为名称的属性)组成的数组
注意:拿不到继承而来的属性,而 for…in 可以拿到继承的属性

更多示例:

var arr = ["a", "b", "c"];
console.log(Object.getOwnPropertyNames(arr).sort());
// // ["0", "1", "2", "length"]

2.3 writable 可写的

writable默认为false.

let obj = {}
let newObj = Object.defineProperty(obj, 'a', {value: 1,writable:true,// 可写的 Default:false
})
obj.a = 2
console.log(obj);


通过上述测试可知,当writable为true时,可修改该属性。

其他测试:

2.4 get 获取

  • 当访问该属性时,会调用此函数。
  • 该函数的返回值会被用作属性的值。
let obj = {}
Object.defineProperty(obj, 'a', {// value: 1get() {console.log('get a:', 1);return 1},
})console.log(obj.a);


通过上述测试可知,当我们定义了get()方法后,每次访问该属性都会先调用该方法,且该方法的返回值就是属性的值

2.5 set 设置

let obj = {}
Object.defineProperty(obj, 'a', {// value: 1set(newValue){console.log('set a:',newValue);}
})
obj.a = 2


通过上述测试可知,当我们每次设置或修改该属性时,都会先调用set方法,且该方法有一个参数(也就是被赋予的新值)

2.6 异常

如果一个描述符同时拥有 valuewritablegetset 键,则会产生一个异常。

value || writable <= 不能与之共处 => get || set

以下为 错误 示例:会抛出一个异常

//以下为错误示例
let obj = {}
let newObj = Object.defineProperty(obj, 'a', {value: 1,get() {...}
})
newObj = Object.defineProperty(obj, 'a', {value: 1,set() {...}
})
newObj = Object.defineProperty(obj, 'a', {writable: true, //这里true 和 false 都会抛出异常get() {...}
})
newObj = Object.defineProperty(obj, 'a', {writable: true,//这里true 和 false 都会抛出异常set() {...}
})

以上情况都会出现下面的异常。

2.7 描述符默认值汇总

拥有布尔值的键 configurableenumerablewritable默认值都是 false
属性值和函数的键 value、get 和 set 字段的默认值为 undefined

三、案例

3.1 自定义 set 和 get

3.1.1 实现一个自存档类

function Archiver() {let archive = []let item = nullObject.defineProperty(this, 'item', {set(newValue) {item = newValuearchive.push({ item: newValue })},get() {console.log('get!');return item}})this.getArchiver = () => archive
}let person = new Archiver()person.item = 'pengsir'
person.item = '彭先生'
console.log(person.item);
console.log(person.getArchiver());

测试结果:

3.1.2 get总是返回相同的属性值

let pattern = {get() {return '我默认是18岁!'},set() {this.age = 18}
}
function TestDefineSetAndGet() {Object.defineProperty(this, 'uname', pattern)
}
let obj = new TestDefineSetAndGet()
obj.uname = '彭先生'
console.log(obj);

测试结果:

3.2 继承属性时的一些注意事项

如果访问者的属性是被继承的,它的 get 和 set 方法会在子对象的属性被访问或者修改时被调用。如果这些方法用一个变量存值,该值会被所有对象共享。

function Star() { }
let attribute = null
Object.defineProperty(Star.prototype, 'x', {set(newValue) {attribute = newValueconsole.log('set!:', newValue);},get() {console.log('get!');return attribute}
})let ldh = new Star()
let zxy = new Star()ldh.x = 1
console.log(ldh.x);
console.log(zxy.x);

测试结果:

如何让继承属性的同时,值不是共享的呢?

这可以通过将值存储在另一个属性中解决。在 get 和 set 方法中,this 指向某个被访问和修改属性的对象。


function Star() { }
let attribute = null// 属性值共享:
// Object.defineProperty(Star.prototype, 'x', {//   set(newValue) {//     attribute = newValue
//     console.log('set!:', newValue);
//   },
//   get() {//     console.log('get!');
//     return attribute
//   }
// })// 属性值不共享:
Object.defineProperty(Star.prototype, 'x', {set(newValue) {this.attribute = newValueconsole.log('set!:', newValue);},get() {console.log('get!');return this.attribute}
})let ldh = new Star()
let zxy = new Star()ldh.x = 1
console.log(ldh.x);
console.log(zxy.x);

测试结果:

继承的值是不可写的(writable) ,那么子对象的值是否可写呢?

//'use strict';function Star() { }
Star.prototype.x = 1
Object.defineProperty(Star.prototype, 'y', {writable: false,value: 2
})let instance = new Star()instance.x = 111
console.log(instance.x);  // 111
console.log(Star.prototype.x); // 1instance.y = 222console.log(instance.y); // 2  => 在严格模式下会报错
// Uncaught TypeError: Cannot assign to read only property 'y' of object '#<Star>console.log(Star.prototype.y); // 2

四、Object.defineProperties()

参数都相同,只是可以同时定义多个属性。

Object.defineProperties(obj, {name: {configurable: true,enumerable: true,writable: true,value: "why",},age: {configurable: false,enumerable: false,get() {return this._age;},set(value) {this._age = value;},},
});

彻底掌握 Object.difineProperty相关推荐

  1. 做diff_Vue3.0时代你必须了解的:diff算法原理和优化

    关注前端公众号 [前端每日一博] 前言 面试官: 你知道 Vue3.0 Object.difineProperty和vue3.0的proxy的区别吗? 你知道 Vue3.0 diff算法原理和它有什么 ...

  2. 在kotlin companion object中读取Bean,注入Bean对象

    在kotlin companion object中读取Bean,注入Bean对象 在使用kotlin时,或多或少地会使用到一些公共组件,如 http. mongo. redis相关的组件.   使用组 ...

  3. 在kotlin companion object中读取spring boot配置文件,静态类使用@Value注解配置

    在kotlin companion object中读取配置文件 静态类使用@Value注解配置 class Config {@Value("\${name}")fun setNam ...

  4. Object的finalize()方法的作用是否与C++的析构函数作用相同

    Object的finalize()方法的作用是否与C++的析构函数作用相同 public class Finalization {private static Finalization finaliz ...

  5. libgstreamer-1.0.so.0: cannot open shared object file: No such file or directory

    1. 问题现象 error while loading shared libraries: libgstreamer-1.0.so.0: cannot open shared object file: ...

  6. RuntimeError: Expected object of backend CUDA but got backend CPU for argument

    RuntimeError: Expected object of backend CUDA but got backend CPU for argument #4 'mat1' 原因:变量没有加cud ...

  7. RuntimeError: Expected object of device type cuda but got device type cpu for argument pytorch数据位置

    RuntimeError: Expected object of device type cuda but got device type cpu for argument #2 'target' i ...

  8. Python错误:AttributeError: 'generator' object has no attribute 'next'解决办法

    今天在学习生成器对象(generation object)运行以下代码时,遇到了一个错误: #定义生成器函数 def liebiao(): for x in range(10): yield x #函 ...

  9. Java OOP(Object Oriented Programming)个人理解及总结

    面向对象编程(Object Oriented Programming,OOP,面向对象程序设计) 其三大特征:封装,继承,多态: 封装:解决数据的安全问题. 继承:解决代码的重用问题. 多态:解决程序 ...

最新文章

  1. Python使用matplotlib函数subplot可视化多个不同颜色的折线图、自定义数据点的形状、自定义折线图的颜色
  2. 香港科技大学谢知遥教授实验组招收机器学习全奖博士生
  3. Mysql-cobar集群安装部署手册
  4. django构建网页_通过解决问题的方式学习django,律师如何构建副业
  5. mysql:Failed to read auto-increment value from storage engine
  6. HTML 取消超链接下划线
  7. 浏览器指纹实现方案:Cookie、Flash Cookies、帆布指纹识别
  8. 利用 dbghelp.dll 生成 dump 文件
  9. mybatis3 配置文件解析
  10. Python爬虫解析网页的4种方式 值得收藏
  11. 美国红帽软件公司是做什么的
  12. 苹果电脑装系统出现未能与服务器取得联系,Mac您的磁盘未能分区 Mac磁盘分区出错解决办法...
  13. 怎么用dos命令打开计算机,如何使用DOS命令打开C盘下的文件夹dos如何打开文件夹...
  14. 山东科技大学计算机学院陈卓艳,转发教务部表彰大学生学习竞赛获奖单位和个人通知...
  15. 安装Centos8设置基础软件仓库时出错
  16. MAE源代码理解 part2 : 预训练调试
  17. jcp jsr_JCP成为“可怕的单一文化”
  18. poi导入excel日期处理_POI处理Excel中各种日期格式问题
  19. 有衬线字体 无衬线字体_字体101:衬线与无衬线
  20. VM虚拟机下载与安装

热门文章

  1. win10系统怎么设置uefi启动?超详细教程献上!
  2. 详解 Flutter State 生命周期
  3. 数据结构与算法Java版学习教程,最适合新手入门(通俗易懂)
  4. 学习笔记(01):巫妖王51单片机开发板配套视频课程-查询方式矩阵按键
  5. LabVIEW中保存数据的方法
  6. 电脑突然乱码,是黑客入侵?一招教你完美解决
  7. INTJ型人格适合选择哪些专业?
  8. 浅析ATO,MTO和ETO
  9. 利用Office 365 定制企业合同管理平台之定制合同文档!
  10. burpsuit的安装激活以及常见问题的解决办法