什么是属性描述对象(attributes object)?

顾名思义,就是用来描述对象属性的对象.javascript内部提供了一个数据结构,用来描述对象的属性以及控制属性的行为.

比如该对象的某属性是否可写,可遍历等

属性描述符的6个元属性

  1. value 该属性的值,默认是undefined
  2. configurable 表示可配置,默认为true;如果改为false,则无法删除该属性并且无法改变该属性的属性描述符对象(除了value值)
  3. writable 表示该属性值是否可改变,默认为true;如果改为false,则属性值不能改变
  4. enumerable 该属性是否可遍历,如果设置为false,则object.keys和for...in 无法遍历到该属性
  5. get 获取该属性值是会被调用
  6. set 设置该属性值是会被调用

获取属性描述对象

Object.getOwnPropertyDescriptor(对象obj,指定属性);

两个参数,第一个参数是对象,第二个参数是想要获取属性描述符的属性(类型是字符串)

默认情况下,configurable,enumerable,writable都是true

通过Object.defineProperty(对象,属性,{});这样添加的属性,此属性的属性描述符configurable,enumable,writable默认都为false

let obj = {
a:1,
b:2
}
console.dir(Ojbect.getOwnPropertyDescriptor(obj, 'a'));
// 输出
// {configurable: true,
// enumerable: true,
// value: 1,
// writable: true} Object.defineProperty(obj,'c',{});
console.dir(Object.defineOwnPropertyDescriptor(obj,'c'));
// 输出
// {configurable: false,
// enumerable: false,
// value: undefined,
// writable: false}

注意: Object.getOwnPropertyDescriptor(obj, 属性); 只能用在对象自身的属性,不能用于继承过来的属性

获取对象自身的属性名

  1. Object.keys(obj)
  2. Object.getOwnPropertyNames(obj)

区别,Object.keys(obj)返回对象自身可枚举的属性;Object.getOwnPropertyNames(obj)会返回对象自身的全部属性,不管是否可遍历

// 声明定义对象
let obj = {
a: 1,
b: 2
}
// 给对象obj添加一个属性c,并且属性c不可枚举(不可遍历)
Object.defineProperty(obj, 'c', {
enumerable: false
});
// 输出对象obj所有键
console.log(Object.keys(obj));
console.log(Object.getOwnPropertyNames(obj));
// 可以看出Object.keys()可以吧对象自身的所有不可枚举的属性打印出来
// Object.getOwnPropertyNames()可以吧对象自身的所有属性都可以打印出来

定义属性描述对象

可以使用Object.defineProperty(obj, propertyName, attrObject);来定义一个属性描述对象

用法,三个参数:

  1. obj 要定义的对象
  2. propertyName 属性名(如果对象上没有此属性则新加此属性,如果对象上有此属性则更新此属性的属性描述对象)
  3. attrObject 定义的对象上的属性描述符对象

如果一次性修改或定义多个属性的属性描述符对象,则可以使用Object.defineProperties(obj, { key1: key1AttrbuteObject, ... });

注意: 如果属性描述符定义了存取器(get,set),就不能再设置writable,或者value,否则会报错

let obj = {
a: 1
}
Object.defineProperty(obj, 'a', {
// 情况一
// writable: false,
// 情况二
// wirtable: true,
// 情况三
value: 123,
get: function(){
console.log('get方法');
}
});
// 以上情况都会报错
// Uncaught TypeError: Invalid property descriptor. Cannot both specify accessors and a value or writable attribute, #<Object>

判断某个属性是否可以枚举(可遍历)

使用propertyIsEnumerable(属性名)可以判断该属性是否可以枚举,propertyIsEnumerable(属性名)是定义在实例对象上的,也就是Object.prototype.propertyIsEnumerabl(),只要是Object的实例都可以访问

propertyIsEnumerable()只能判断自身的属性,如果判断的是继承过来的属性或者自身不存在的属性,则直接返回false

let obj = {
b: 2
}
Object.defineProperty(obj, 'a', {
enumerable:false
});
// 自身可枚举的属性 true
console.log(obj.propertyIsEnumerable('b'));
// 自身不可枚举的属性 false
console.log(obj.propertyIsEnumerable('a'));
// 继承过来的属性 false
console.log(obj.propertyIsEnumerable('toString'));
// 自身不存在的属性 false
console.log(obj.propertyIsEnumerable('c'));

属性描述符的元属性

  1. writable

    决定该属性是否可以改变值,false不可以改变;true可以改变(不能与get/set同时存在)

    如果writable为false,再改变值的话还是之前的值;如果是严格模式会报错

  2. enumerable

    决定该属性是否可以枚举

    enumerable为false时,以下三个不会取到该属性

    • for...in...
    • Object.keys()
    • JSON.stringify()
    let obj = {
    a: 1,
    }
    Object.defineProperty(obj, 'a', {
    value: 123,
    enumerable: false
    });
    // 123
    console.log(obj.a);
    // []
    console.log(Object.keys(obj));
    // {}
    console.log(JSON.stringify(obj));
  3. value

    读取或者改写属性的值

    let obj = {
    a: 1
    }
    // 读取值
    console.log(Object.getOwnPropertyDescriptor(obj,'a').value);
    // 改写值
    Object.defineProperty(obj, 'a', {vaue: 123});
  4. configurable

    configurable决定了属性的可配置性,当configurable为false时,value\enumerable\writable\configurable都不可以修改配置,并且不能使用delete删除该属性

  5. get

  6. set

    也可以称为存取器

    两种写法:

    一,Object.defineProperty(obj,'a',{get: function(){ }})

    二,var obj = {get p(){},set p(val)

    var obj = Object.defineProperty({}, 'a', {
    get: function(){
    return 'getter';
    },
    set: function(){
    console.log('a的set方法');
    }
    }); var obj1 = {
    get a(){
    return 'getter'
    },
    set a(){
    console.log('a的set方法');
    }
    }

对象的拷贝

浅拷贝

  1. 直接赋值引用

    问题是改变一个对象的属性值会影响到另一个
    let obj = {a:1}
    let objC = obj;
    objC.a = 2;
    // 因为obj和objC指向同一个内存地址,所以改变objC必然会影响到obj
  2. 将对象的每个属性及属性值赋给拷贝对象

    问题是如果被拷贝的对象的某一属性值是对象的话,拷贝的还是引用,还是会相互影响的
    // 被拷贝的对象
    let obj = {a:1, b: { c:2 }}
    let objC = {}
    for(let key in obj){
    if(!obj.hasOwnProperty(key))continue;
    objC[key] = obj[key]
    }
    objC.b.c = 3;
    // 因为objC和obj的属性b都指向同一个地址,所以会相互影响

    以上的方式不能够拷贝属性的存取器

    let obj = {get a(){return 1},get b(){return 2}}
    let objC = {}
    for(let key in obj){
    // 因为Object.getOwnPropertyDescriptor()只能获取自身的,获取不到继承的属性,会报错
    if(!obj.hasOwnProperty(key))continue;
    Object.defineProperty(objC, key, Object.getOwnPropertyDescriptor(obj, key));
    }

深拷贝

function extend(to,from){
for(let fr in from){
if(!from.hasOwnProperty(fr))continue;
if(typeof from[fr] === 'object'){
if(Object.prototype.toString.call(from[fr]) === '[object Object]'){
to[fr] = {};
extend(to[fr], from[fr]);
// console.log(Object.prototype.toString.call(from[fr]));
}else if(Object.prototype.toString.call(from[fr]) === '[object Array]'){
to[fr] = [];
for(let i=0;i<from[fr].length;i++){
to[fr][i] = from[fr][i]
}
}
}else{
to[fr] = from[fr];
}
}
return objC;
}

控制对象的状态

冻结对象的读写状态,防止对象被改变

  1. Object.preventExtension(obj);

    // 阻止对象添加属性

    // 判断对象是否可以被扩展

    Object.isExtensible(obj)
  2. Object.seal(obj)

    // 阻止对象添加属性和删除旧属性

    // 判断是否使用了seal方法

    Object.isSealed(obj)

    使用了Object.seal(obj)之后,Object.isExtensible(obj)也变为false
  3. Object.freeze(obj)

    // 使得对象扩展属性,删除属性,并且值也不能改变,变成了常量

    // 判断对象是否用了freeze方法

    Object.isFrozen(obj)

    使用了Object.freeze(obj)之后,Object.isSealed(obj)返回true,Object.isExtensible(obj)返回false

javascript的属性描述符的更多相关文章

  1. JavaScript.descriptor(属性描述符)

    属性描述符是对JavaScript属性的描述,包括:value.writable.enumerable.configurable,除value其他默认为true. 本文包括: 取得属性描述符. Obj ...

  2. 深入理解javascript对象系列第三篇——神秘的属性描述符

    × 目录 [1]类型 [2]方法 [3]详述[4]状态 前面的话 对于操作系统中的文件,我们可以驾轻就熟将其设置为只读.隐藏.系统文件或普通文件.于对象来说,属性描述符提供类似的功能,用来描述对象的值 ...

  3. 理解JavaScript中的属性描述符

    我们把描述JavaScript中定义内部特性的属性叫做属性描述符 分为两大类:数据描述符和存取描述符 数据描述符是一个拥有可写或不可写的属性(Writable); 存取描述符不包含数据值,是一组拥有g ...

  4. JavaScript 属性描述符

    属性描述符(Property Descriptor)是 ES5 之后出现的概念,顾名思义,它用于描述属性应该是什么样,例如是否只读,能否枚举,能否可配置等.所有对象属性均可使用属性描述符来定义. 属性 ...

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

    Python:高级主题之(属性取值和赋值过程.属性描述符.装饰器) 背景 学习了Javascript才知道原来属性的取值和赋值操作访问的“位置”可能不同.还有词法作用域这个东西,这也是我学习任何一门语 ...

  6. JS属性描述符之Object.defineProperty()定义对象属性特性

    一.Object.defineProperty的作用 用来给对象新增属性,和修改对象中的属性. 二.JS对象中的描述符 js对象中两种属性描述符:数据描述符和存取描述符(访问描述符). 注意事项: 1 ...

  7. Object.defineProperty 与 属性描述符

    为JavaScript对象新增或者修改属性,有两种不同方式:直接使用=赋值或者使用Object.defineProperty 定义,使用后者的话还可以设置属性的描述符. Object.definePr ...

  8. JS属性描述符

    var myObject = { a:2 }; Object.getOwnpropertyDescriptor(myObject,"a"); { value:2, writable ...

  9. Python 属性描述符和属性的查找过程

    属性描述符可以用来控制给属性赋值的时候的一些行为 import numbers class IntField: def __get__(self, instance, owner): return s ...

  10. python之属性描述符与属性查找规则

    描述符 import numbers class IntgerField: def __get__(self, isinstance, owner): print('获取age') return se ...

随机推荐

  1. [常用工具] PyAutoGUI使用教程

    PyAutoGUI使用教程 目录 PyAutoGUI使用教程 1 基础知识 2 一般函数 3 故障保险 4 鼠标函数 4.1 鼠标移动 4.2 鼠标拖动 4.3 鼠标单击 4.4 鼠标滚动 4.5 鼠 ...

  2. [机器学习] 特征选择笔记4-使用SelectFromModel特征选择

    特征选择 代码下载 本文主要介绍sklearn中进行特征选择的方法. sklearn.feature_selection模块中的类可用于样本集的特征选择/降维,以提高估计量的准确性得分或提高其在超高维 ...

  3. Dubbo架构设计与源码解析(二) 服务注册

    作者:黄金 一.Dubbo简介 Dubbo是一款典型的高扩展.高性能.高可用的RPC微服务框架,用于解决微服务架构下的服务治理与通信问题.其核心模块包含 [RPC通信] 和 [服务治理] ,其中服务治 ...

  4. shell端口监听异常邮箱告警

    业务场景:应用发布监听服务是否正常启动,因为服务器资源不够上不了prometheus.grafana,所以写的shell脚本监听.此脚本适用于初创公司及小微企业使用. 准备工作 除了shell脚本这里 ...

  5. 使用prometheus来避免Kubernetes CPU Limits造成的事故

    使用prometheus来避免Kubernetes CPU Limits造成的事故 译自:Using Prometheus to Avoid Disasters with Kubernetes CPU ...

  6. Java基础1-1-2—java基础语法(运算符)

    2. 运算符 2.1 算术运算符 运算符和表达式 运算符:对常量或者变量进行操作的符号 表达式:用运算符把常量或者变量连接起来符合java语法的式子就可以称为表达式. 不同运算符连接的表达式体现的是不 ...

  7. 在GCP的Kubernetes上安装dapr

    1 简介 我们之前使用了dapr的本地托管模式,但在生产中我们一般使用Kubernetes托管,本文介绍如何在GKE(GCP Kubernetes)安装dapr. 相关文章: dapr本地托管的服务调 ...

  8. Windows性能监控工具Perfmon的使用、性能指标分析

    Fighting_001 关注  0.1 2018.08.25 22:18* 字数 1488 阅读 7604评论 0喜欢 4 目录结构 一.Perfmon简介.性能监控指标.性能对象指标 1.常用的性 ...

  9. 基于View接口

    目录 基于View接口 1.写模型表以及数据库迁移 3.使用CBV写查询所有的视图接口 4.配路由 基于View接口 ​ Django原生即继承View来实现写接口,的确过程很繁杂,很多东西都是手动写 ...

  10. USACO 2023 January Contest, Bronze Problem 3. Moo Operations

    这道题目灰常简单,我们先从最简单的3个字符串开始 有以下几种情况: 可以看到,只有在中间是O的情况下才有可能变成MOO 辣么我们不妨在在s串中枚举这个中间 O 每枚举到一个就看看能不能用他的本身操作次 ...