对象的属性描述符是一个初学者容易忽略但是非常重要的特性,像是vue的数据双向绑定就是用它做文章。且关于它的方法和属性也很多,今天我来总结一下。

属性描述符概述

  对象的每个属性都具备了属性描述符,它描述了属性的一些特性。一共有四个特性,分别为value(值)、writable(可写)、enumerable(可枚举)和configurable(可配置)。只设置属性值的属性描述符也被称为数据描述符。
  这里我们介绍两个方法,Object.getOwnPropertyDescriptor()以及Object.defineProperty()。

//Object.getOwnPropertyDescriptor()第一个参数为某个对象,第二个参数为某个对象上的某个属性,返回这个属性的属性描述符。
//默认writable、enumerable和configurable都为true
let obj = {foo: 123,bar: 456
}
console.log(Object.getOwnPropertyDescriptor(obj, 'foo'))
输出为:
{ value: 123,writable: true,enumerable: true,configurable: true
}
复制代码
//Object.defineProperty()可以给某个对象添加一个新属性或者修改某个对象的一个已有属性(前提是configurable为true)
Object.defineProperty(obj, 'baz', {value: 789,writable: true,enumerable: true,configurable: true
})
console.log(obj.baz) //789
复制代码

writable

  writable决定是否可以修改属性的值,这个不可修改是指通过.或者[]在对象上修改该属性是会出错的,但是通过属性描述符还是可以修改的。

let obj = {}
Object.defineProperty(obj, 'baz', {value: 1,writable: false,enumerable: true,configurable: true
})
console.log(obj) //{ baz: 1 }
Object.defineProperty(obj, 'baz', {value: 2,writable: false,enumerable: true,configurable: true
})
console.log(obj) //{ baz: 2 }
obj.baz = 3 //这样是无法修改baz属性的
console.log(obj) //{ baz: 2 }
复制代码

configurable

  configurable决定属性是否可以通过Object.defineProperty方法来修改属性描述符。configurable一旦设置是不可逆的,设置之后它除了不允许配置属性描述符以外,还不允许通过delete删除该属性。

let obj = {}
Object.defineProperty(obj, 'baz', {value: 1,writable: true,enumerable: true,configurable: false
})
console.log(obj) //{ baz: 1 }
obj['baz'] = 3 //还是可以通过这种方式来修改属性的值
console.log(obj) //{ baz: 3 }
delete obj.baz
console.log(obj) //{ baz: 3 }没删掉,但前一句不会报错
Object.defineProperty(obj, 'baz', {  //TypeError: Cannot redefine property: bazvalue: 2,writable: true,enumerable: true,configurable: false
})
复制代码

enumerable

  enumerable被称为可枚举性,如果该属性为false,则表示某些操作会忽略当前属性。es5有三个操作:for...in、Object.keys、JSON.stringify,再加上es6的Object.assign方法,一共四个操作会忽略不可枚举的属性。

属性的遍历

  1. for...in:循环遍历对象自身的和继承的可枚举的属性。
  2. Objects.keys(obj):返回一个数组,包括对象自身(不含继承)的所有可枚举属性。所以说对象的遍历一般用该方法。
  3. Object.getOwnPropertyNames(obj):返回一个数组,包括对象自身(不含继承)的所有属性。包含不可枚举的属性。

let proto = { y: 1, z: 2 };
let obj = { x: 10 }
Object.defineProperty(obj, 'foo', {value: 3,writable: true,enumerable: false,configurable: false
})
Object.setPrototypeOf(obj, proto);
Object.getOwnPropertyNames(obj).forEach(key => console.log(obj[key]))  //10,3for (let key in obj) {console.log(obj[key]); //10,1,2
}Object.keys(obj).forEach(key => console.log(obj[key])) //10
复制代码

  4. Object.getOwnPropertySymbols(obj):返回一个数组,包含对象自身的所有Symbol属性。
  5. Reflect.ownKeys(obj):返回一个数组,包含自身所有属性,包括Symbol属性和不可枚举属性。

[[Get]]和[[Put]]

  属性的[[Get]]操作会从该对象自身属性开始,沿着它的原型链寻找是否有名称相同的属性,如果找到就返回该属性的值,如果自始至终都没找到值,就返回undefined。   [[Put]]操作则涉及两种情况。一个是已经存在该属性,如果存在且有setter就调用setter,如果writable为false,则静默失败,如果这两者都不是,将该值设置为属性的值。如果对象中不存在该属性,就涉及到原型链的问题,下一节在原型及原型链中总结。
  getter和setter方法可以部分改写默认的[[Get]]和[[Put]]操作,getter在获取属性值时调用,setter在设置属性值时调用。当给一个属性设置getter和setter之后,这个属性的属性描述符也被称作访问描述符,Js会忽略掉它的writable和value特性,用get来取代value,用set取代writable。
  getter和setter有两种定义方式,一种在对象中直接定义,一种通过Object.defineProperty定义。

let val = 2;
let obj = {get a() {return val;},set a(newVal) {if (val === newVal) {return;}val = newVal * 2;}
}obj.a = 4;
console.log(obj.a); //8
obj.a = 3;
console.log(obj.a); //6
复制代码

相当于:

let val = 2;
let obj = {};
Object.defineProperty(obj, 'a', {get: function() {return val;},set: function(newVal) {if (val === newVal) {return;}val = newVal * 2;}
})
obj.a = 4;
console.log(obj.a);//8
obj.a = 3;
console.log(obj.a);//6
复制代码

存在性

  例如'a' in myobj操作符和myobj.a/myobj[a]都是在整个原型链上查找查找该对象是否有该属性。相比之下,myobj.hasOwnProperty('a')方法只会在myobj这个对象中查找该属性,而不会去原型链中查找。
  hasOwnProperty是Object.prototype上的方法,通过Object.create(null)创建的对象是无法使用该方法的。

let myobj = {a: 1
}
let proto = {b: 2
}
Object.setPrototypeOf(myobj, proto);console.log('a' in myobj); //true
console.log('b' in myobj); //trueconsole.log(myobj.hasOwnProperty('a')) //true
console.log(myobj.hasOwnProperty('b')) //false
复制代码

  部分内容参考《你不知道的JavaScript上》和《ES6标准入门》。

JavaScript(3)之——对象的属性描述符相关推荐

  1. JavaScript 属性描述符

    前言   此文总结了属性描述符的作用和特性,以及限制对象操作的部分方法. Object.defineProperty   Object.defineProperty 用于指定对象属性的描述符.   函 ...

  2. javascript --- 属性描述符

    从ES5开始,所有的属性都具备了属性描述符 var myObject = {a: 2 };Object.getOwnPropertyDescriptor(myObject, "a" ...

  3. Javascript高级教程:数据属性描述符与存储属性描述符

    属性描述符 let obj = {name: "ziu",age: 18 } Object.defineProperty(obj, "height", {val ...

  4. Python:高级主题之(属性取值和赋值过程、属性描述符、装饰器)

    属性取值和赋值过程 一切皆是对象,类型也是对象. 对象包含一个__class__属性指向其所属类型. 对象包含一个__dict__属性指向其所包含的成员(属性和方法). 取值过程(下面是伪代码) 1 ...

  5. JavaScript 中遍历对象的属性

    原文链接 JavaScript 中遍历对象的属性 参考 JavaScript中的属性:如何遍历属性 <JavaScript 高级程序设计> 概述 遍历 JavaScript 对象中的属性没 ...

  6. ES6-8 - 函数名/对象拓展、描述符、getter/setter

    函数名 有两种特殊情况:bind方法创造的函数,name属性返回bound加上原函数的名字:Function构造函数创造的函数,name属性返回anonymous. bind函数名 // 以bound ...

  7. JavaScript 中遍历对象的属性 1

    JavaScript 中遍历对象的属性 原文链接 JavaScript 中遍历对象的属性 参考 JavaScript中的属性:如何遍历属性 <JavaScript 高级程序设计> 概述 遍 ...

  8. python 属性描述符_Python属性描述符(二)

    Python存取属性的方式特别不对等,通过实例读取属性时,通常返回的是实例中定义的属性,但如果实例未曾定义过该属性,就会获取类属性,而为实例的属性赋值时,通常会在实例中创建属性,而不会影响到类本身.这 ...

  9. python 属性描述符

    文章目录 1. 描述符示例:验证属性 2. 自动获取储存属性的名称 3. 继承改进 4. 覆盖型与非覆盖型描述符对比 4.1 覆盖型描述符 4.2 没有 `__get__` 方法的覆盖型描述符 4.3 ...

最新文章

  1. 程序员如何切入区块链去中心化应用开发
  2. HashMap为什么是线程不安全的?
  3. Mind Control CodeForces - 1291C(思维)
  4. ie浏览器网页版进入_荟萃浏览器v2.10.2清爽版 网页秒开/装机必备
  5. [C++11] 右值引用和移动语义
  6. 问题 1020: [编程入门]猴子吃桃的问题
  7. 08CMS之新建独立页面
  8. java爬取百度图片
  9. 用5000字长文记录华为仓库服务GaussDB(DWS)上手过程【这次高斯不是数学家】
  10. 计算机高程知识点,工程测量重点全部知识点(中国矿业大学)
  11. ibmr系列服务器怎么装架子,R440/R540/R640/R740 R820 R930 DELL服务器导轨 滑轨 支架 理线架...
  12. web3d-手机产品展示_onePlus6
  13. 【软件测试工程师】App 应用测试方法以及测试思路
  14. 如何用Python面向对象实现盖伦和瑞文互殴?
  15. 单手杀穿经典链表题Pt.2——LeetCode天梯渡劫(倒数第k节点,合并链表,链表分割,回文结构)
  16. win7系统64位MSCOMCTL.OCX丢失或无效解决办法
  17. 【图解UDS】UDS汽车诊断标准协议(ISO 14229)带你入门到精通
  18. 除以用计算机按哪个键,电脑键盘÷号是哪个键?小编教你打出÷符号的操作方法...
  19. MySQL No compatible servers were found.You’ll need to cancel this wizard and install one
  20. 【有图有真相】北京地区午饭线下活动——香山行圆满结束

热门文章

  1. CSS3的过渡和动画
  2. Java位运算在程序设计中的使用:位掩码(BitMask)
  3. PHP版本VC6与VC9/VC11/VC14、Thread Safe与None-Thread Safe等的区别
  4. FreeSWITCH IVR中lua调用并执行nodejs代码
  5. 转换营销阵地 特步的世界杯身影
  6. iconfont 在vue项目中的应用(icon-component组件)
  7. IntelliJ IDEA添加过滤文件或目录
  8. poj——2771 Guardian of Decency
  9. jQuery 技术揭秘
  10. 端口聚合与Trunk综合配置