js 中的对象属性——configurable、writable 等(数据属性和访问器属性)_js configurable-程序员宅基地

技术标签: javaScript  javascript  

其他相关笔记还有以下几篇:

1. 属性类型

使用对象字面量或者构造函数实例化对象并为其添加属性和方法后,它们的这些属性在创建时都带有一些特征值,JavaScript 通过这些特征值来定义这些属性的行为。而对象中的属性其实可以分为两类,分别是数据属性和访问器属性。这两类属性具有的特性有些差异。

数据属性

数据属性包含一个数据值的位置。在这个位置可以读取和写入值。这类属性有 4 个描述其行为的特性

  • [[Value]] : 包含这个属性的数据值。读取属性时从这个位置读取;写入属性时,把新值保存在这个位置。这个特性的值默认为 undefined 。
  • [[Writable]] : 表示能否修改属性的值,即值是可写的还是只读
  • [[Enumerable]] : 目标属性是否可被枚举(遍历)
  • [[Configurable]] : 表示能否通过 delete 删除属性能否修改属性的特性,或者将属性修改为访问器属性。

无论是 new 加构造函数实例化对象还是对象字面量创建对象并为其添加的属性,这些属性的 [[Value]] 特性被设置为该属性的值,而对它的值的修改都将反映都这个特性上。并且属性的其他三个特性的值都会默认是 true

若需要修改属性默认的特性,必须使用 ES5 的 Object.defineProperty() 方法。它可以定义新属性并设置其特性或者改变属性的原有特性。用法如下

// 三个参数均为必需参数 
Object.defineProperty(obj, prop, attributeDesc);
  • obj :属性所在的对象(目标对象)
  • prop :定义的新属性或者修改的属性的名字
  • attributeDesc : 属性特性描述对象

使用该方法创建或者修改对象属性时主要注意两点:

  1. 创建属性时如果没有指定属性的 configurable、enumerable 和 writable 特性,默认值都是 false 。
  2. 一旦将属性的 configurable 特性定义为 false ,即不可配置的,该属性就不能再改回可配置的了。此后,再调用 Object.defineProperty() 方法修改除了 writable 特性的特性都会导致错误。(JavaScript 高级程序设计)
    // uname 属性的可配置性、可枚举性、可写性默认都为 true
    var obj = {
    
        uname: '扬尘'
    };
    // 更改 value 和 writable 特性
    Object.defineProperty(obj, 'uname', {
    
        value: 'TKOP_',
        writable: false
    });
    console.log(obj.uname); // ->'TKOP_'
    obj.uname = '试试你能改不?';
    console.log(obj.uname); // ->'TKOP_'
    // 测试uname的可枚举性
    console.log(Object.keys(obj)); // ->['uname']
    Object.defineProperty(obj, 'uname', {
    
        enumerable: false
    });
    console.log(Object.keys(obj)); // ->[]

    // age 属性的可枚举性、可写性默认都是 false 。可配置性为true
    Object.defineProperty(obj, 'age', {
    
        value: 23,
        configurable: true
    });
    console.log(Object.keys(obj)); // ->[]
    obj.age = 18;
    console.log(obj.age); // ->23 回不去的18岁

以上是第一点的代码演示,接下来是第二点。可能稍微有点复杂,演示过程复杂,复制了一般性代码。关于属性设置为不可配置后再次使用该方法配置这四个特性时的特点个人总结如下

  • writable 特性只能由 true 再次改为 false 而不能由 false 改为 true ,这和《JavaScript 高级程序设计》的说法有出入。
  • configurable 和 enumerable 特性可以再次设置不变的值不报错,没有实际意义。但是想改变这两个特性则会报错。
  • value 特性再次改变时是否报错要根据 writable 特性来确定。writable 为 true,则 value 特性改为任何值都不会报错。如果 writable 为 false ,则同样 value 特性也只能再次设置不变的值不报错,没有实际意义。但是想改变其值则会报错。

若总结有错欢迎评论区留言。

      var obj = {
    
        status: '1'
    };
    Object.defineProperty(obj, 'status', {
    
        value: '2',
        configurable: false,
        // enumerable: false,
    });
    obj.status = '2__';
    console.log(obj.status); // ->'2__'
    console.log(Object.keys(obj)); // ->['status']

    Object.defineProperty(obj, 'status', {
    
        value: '3',
        // enumerable: true,
        // enumerable: false,
        // configurable: false,
        // configurable: true,
        writable: false
    });
    obj.status = '3__';
    console.log(obj.status); // ->'3'
    console.log(Object.keys(obj)); // ->['status']

    Object.defineProperty(obj, 'status', {
    
        // writable: true
    })

访问器属性

访问器属性不包含数据值,它们包含两个函数 getter 和 setter(都不是必需的)。在读取访问器属性时,会调用 getter 函数,这个函数负责返回有效的值;在写入访问器属性时,会调用 setter 函数并传入新值,这个函数决定了如何处理数据。这类属性也具有如下四种特性:

  • [[Configurable]] : 表示能否通过 delete 删除属性能否修改属性的特性,或者将属性修改为数据属性。
  • [[Enumaerable]] : 目标属性是否可被枚举(遍历)
  • [[Get]] :在读取属性时调用的函数。默认值是 undefined。
  • [[Set]] : 在写入属性时调用的函数。默认值是 undefined。
    var book = {
    
        _year: 2004,
        edition: 1
    };
    Object.defineProperty(book, 'year', {
    
        get: function() {
    
            return this._year;
        },
        set: function(newValue) {
    

            if (newValue > 2004) {
    
                this._year = newValue;
                this.edition += newValue - 2004;
            }
        }

    });
    book.year = 2010; // 写入属性
    console.log(book.edition, book.year); // -> 7  2010

上面是书中的示例代码,代码中的 book 对象有两个默认属性 edition(版本)和 _year 属性。_year 属性前面的下划线是一种常用标记,表示只用于对象内部方法访问的属性。另一个 year 属性是访问器属性,写入和读取时会分别调用该属性的 set 和 get 特性。读取时调用 get 返回值即为访问器属性的值,写入时调用 set 使 _year 和 edition 随之改变,这也是使用访问器属性的常用方式,即设置一个值会导致其他属性发生改变

为更好理解访问器属性的这两个特性,我对示例作了一下更改。如下,_year 表示出版年份,不会改变。假设以后每年出一个新版本,即每年 edition 属性都会改变。给 book 对象添加一个访问器属性 year ,该属性返回值为现下年份,并使 edition 随之更新

    var book = {
    
        _year: 2004,
        edition: 1
    };
    Object.defineProperty(book, 'year', {
    
        get: function() {
    
            return (new Date()).getFullYear();
        },
        set: function() {
    
            this.edition += this.year - this._year;
        }

    });
    book.year = 2021;
    console.log(book.edition, book.year); // -> 18 2021

访问器属性不包含数据值,即没有存储数值,但是它可以返回有效数值。

    var book = {
    
        _year: 2004,
        edition: 1
    };
    Object.defineProperty(book, 'year', {
    
        set: function() {
    
            this.edition += (new Date()).getFullYear() - this._year;
        }
    });
    book.year = 2010;
    console.log(book.edition, book.year); // -> 18 udefined

上面的代码中只设置了year 属性的 [[Set]] 特性,在访问 year 属性时返回的是 undefined 。只指定 setter 函数的属性不能读,否则会返回 undefined (书中说在严格模式下会报错,但是亲手试了一下好像还是返回 undefined)。若只指定 [[Getter]] 特性,说明该属性只读不可写,尝试写入时会被忽略,严格模式下会报错

    "use strict";
    /*
    * 其他代码
    */
    book.year = 2010; // Uncaught TypeError: Cannot set property year of #<Object> which has only a getter

并不是所有的浏览器都支持 Object.defineProperty() 方法,所以在此之前使用的是两个非标准方法添加访问器属性。__defineGetter__() 和 __defineSetter__() 可以用来创建访问器属性并设置 [[Get]] 和 [[Set]] 特性,但是若浏览器不支持 Object.defineProperty() 方法,则其他两个特性无法更改。

    var book = {
    
        _year: 2004,
        edition: 1
    };
    book.__defineGetter__('year', function() {
    
        return this._year;
    });

    book.__defineSetter__('year', function(newValue) {
    

        if (newValue > 2004) {
    
            this._year = newValue;
            this.edition += newValue - 2004;
        }
    })
    book.year = 2010; // 写入属性
    console.log(book.edition, book.year); // -> 7  2010

2. 同时定义多个属性( defineProperties() )

    var book = {
    };
    Object.defineProperties(book, {
    
        // 数据属性的定义
        _year: {
    
            writable: false,
            value: 2004
        },
        edition: {
    
            writable: true,
            value: 1
        },
        // 访问器属性
        year: {
    
            get: function() {
    
                return (new Date()).getFullYear();
            },
            set: function() {
    
                this.edition += (new Date()).getFullYear() - this._year;
            }
        }
    })

该方法与 Object.defineProperty() 的兼容性一样。

3. Object.getOwnPropertyDescriptor()

这个方法用以读取对象的某个属性的四个特性。接收两个参数,第一个参数是属性所在的对象,第二个参数是需要读取特性的属性名。返回值是包含属性的四个特性的对象。

    var attributes = Object.getOwnPropertyDescriptor(book, 'year');
    console.log(attributes.set); 
    var attributes = Object.getOwnPropertyDescriptor(book, '_year');
    console.log(attributes);

在这里插入图片描述

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/TKOP_/article/details/115018189

智能推荐

吉时利Keithley 4200-SCS参数分析仪_吉时利了4200-scs-程序员宅基地

文章浏览阅读51次。它可以帮助研究人员对不同材料的电学特性进行准确测量和分析。-KEITHLEY吉时利4200-SCS半导体特性分析系统还被广泛应用于功率器件的研究和测试。-在光电子学领域,KEITHLEY吉时利4200-SCS半导体特性分析系统可用于测量光电二极管和太阳能电池等器件的性能。它为学生和研究人员提供了一个实验平台,可以进行各种半导体器件的测量和分析实验,促进他们的学习和研究成果。-在半导体器件制造过程中,KEITHLEY吉时利4200-SCS半导体特性分析系统可用于对制造过程中的器件进行测试和质量控制。_吉时利了4200-scs

Casey 正统 Runes 协议的发行和转账|本地 Bitcoin 网络实操_比特币符文部署教程-程序员宅基地

文章浏览阅读991次,点赞22次,收藏18次。Casey 正统 Runes 协议的发行和转账|本地 Bitcoin 网络实操 _比特币符文部署教程

java outputstream api_java – 从OutputStream创建一个文件-程序员宅基地

文章浏览阅读648次。我有这个问题,我正在创建一个文件,但这是创建空文件.我使用的是Dropbox的API,Dropbox的代码运行良好,但我不知道我不好.我已经为我的应用程序使用了2º和3º代码,这是运行良好.这通过分层次操作.我正在发送outputStream用于功能.但这是空的.我正在使用outputStream,因为我需要它与outputstream一起运行.1º代码(Class Test || Call):F..._outputstream生成文件

毕设文献翻译2_KEY-INVARIANT CONVOLUTIONAL NEURAL NETWORK TOWARD EFFICIENT COVERSONG IDENTIFICATION-程序员宅基地

文章浏览阅读917次,点赞23次,收藏23次。KEY-INVARIANT CONVOLUTIONAL NEURAL NETWORK TOWARD EFFICIENT COVERSONG IDENTIFICATION

getopt未定义问题_“getopt”: 找不到标识符-程序员宅基地

文章浏览阅读1.5k次。今天又在windows的visual studio上编译错误的时候,提示找不到 getopt ,optarg。以及unistd.h。 修改方法:在vs的头文件里面,加一个文件unistd.h,在这个头文件里面加入#include <io.h>#include <process.h>,然后在github上下载一个https://github.com/matthkl..._“getopt”: 找不到标识符

设计模式 模板模式和策略模式_策略模式 模板模式-程序员宅基地

文章浏览阅读4k次。模板模式和策略模式,有相识的地方,都是通过对钩子方法的调用,来实现一个业务的完整逻辑。所以这里我将两种模式放在一起介绍,比较容易加深对这两种模式的理解。模板模式在模板模式(Template Pattern)中,一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。这种类型的设计模式属于行为型模式。例子假设我们需要设计两款游戏,他登录账号的方式是一样的,然后开始游戏和结束游戏的行为是不一样的,那么我们可以用模板模式来实现这个逻辑。类图_策略模式 模板模式

随便推点

Android开发之PopupWindow(实现弹窗)_android popupwindow-程序员宅基地

文章浏览阅读6.8k次,点赞8次,收藏36次。包括唤出弹窗、弹窗内容的自定义与监听。_android popupwindow

TOMCAT 中间件安全加固_中间件加固方案-程序员宅基地

文章浏览阅读228次。对于一些常见的错误页面,我们可以在配置文件/etc/tomcat/web.xml中,重定向403、404以及500错误到指定页面。在这里插入图片描述我们现在在web.xml配置文件中加入error-page参数。在这里插入图片描述我们现在编辑我们的错误页面。该错误页默认放在我们webapps目录中。在这里插入图片描述这里是我们tomcat默认的页面所在位置。在这里插入图片描述重启tomcat服务,我们可以看到,页面为我们自定义的错误页面了。在这里插入图片描述。_中间件加固方案

layui实现数据表格table的搜索功能_layui table查询-程序员宅基地

文章浏览阅读3.1k次,点赞2次,收藏10次。layui根据特定信息对表格进行搜索并显示效果实现html部分js部分Controller层Mapper层注意总结效果先放效果图此处根据“角色名称”进行搜索,得到效果实现html部分此处注意!!需要要为input、table里边加上“id”属性,在js部分需要特定进行获取。<div class="layuimini-container"> <div class="layuimini-main"> _layui table查询

机器学习中的数学——深度学习优化的挑战:病态_优化函数 病态-程序员宅基地

文章浏览阅读1.5w次,点赞5次,收藏7次。优化通常是一个极其困难的任务。传统的机器学习会小心设计目标函数和约束,以确保优化问题是凸的,从而避免一般优化问题的复杂度。在训练神经网络时,我们肯定会遇到一般的非凸情况。即使是凸优化,也并非没有任何问题。在本文中,我们会总结几个训练深度模型时会涉及的主要挑战。病态在优化凸函数时,会遇到一些挑战。这其中最突出的是Hessian矩阵HHH的病态。这是数值优化、凸优化或其他形式的优化中普遍存在的问题。病态问题一般被认为存在于神经网络训练过程中。病态体现在随机梯度下降会“卡”在某些情况,此时即使很小的更新步长也_优化函数 病态

Spring Boot配置文件_server: port: 8084 spring: application: name: insi-程序员宅基地

文章浏览阅读356次。idea小技巧:Alt+Ins:快速调出getter、setter方法或toString等方法。二、配置文件1、配置文件SpringBoot使用一个全局的配置文件,配置文件名是固定的;application.propertiesapplication.yml配置文件的作用:修改SpringBoot自动配置的默认值;SpringBoot在底层都给我们自动配置好;YAML(YAML Ain’t Markup Language)​ YAML A Markup Langu._server: port: 8084 spring: application: name: insideoperation-server profile

jetpack compose原理解析-程序员宅基地

文章浏览阅读3.4k次,点赞7次,收藏7次。目录jetpack compse原理解析jetpack compse声明式ui开发原理分析整体框架介绍compose LayoutNode布局介绍@Composeable注解实现细节属性更新小结jetpack compse原理解析jetpack compseJetpack Compose是Google在2019 I/O大会上公布开源的一个非捆绑工具包。Jetpack Compose是用于构建原生Android UI的现代工具包。 Jetpack Compose使用更少的代码,强大的工具和直观的Kotl_jetpack compose原理

推荐文章

热门文章

相关标签