• Object.defineProperty设置对象属性


    8.1.1 属性的类型

      建议观看一个教学视频再看下面内容更容易理解:Object.defineProperty

      ECMAScript 中有两种属性:数据属性访问器属性

    • 数据属性

      数据属性是用来保存数据的,其中有 4 个描述其行为的特性,其中有一个特性 [[Value]] 是存放值的位置,这个位置可以读取和写入设置的属性的值。四个特性如下:

    ① [[Configurable]]:表示能否通过 delete 删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性。像前面例子中直接在对象上定义的属性,该特性的默认值都是 true。

    ② [[Enumerable]]:表示能否通过 for-in 循环返回属性。像前面例子中直接在对象上定义的属性,该特性的默认值都是 true。

    ③ [[Writable]]:表示能否修改属性的值。像前面例子中直接在对象上定义的属性,该特性的默认值都是 true。

    ④ [[Value]]包含这个属性的数据值。读取属性值的时候从这个位置读;写入属性的时候,把新值保存在这个位置。这个特性的默认值为 undefined。

      要修改属性的默认的特性,必须使用 ECMAScript5 中的 Object.defineProperty() 方法。这个方法接收三个参数:属性所在的对象属性的名字、和一个描述符对象。其中,描述符对象的属性必须是:configurable、enumerable、writable 和 value。设置其中一个或多个值。例如:

    var person = {};
    Object.defineProperty(person,"name",{
        writable: false,        // 设置"name"属性的 writable 特性值为 false,
        value: "andy"
    });
    alert(person.name);         // andy
    person.name = "Grey";       // 尝试修改属性值,无效
    alert(person.name);         // andy,不可修改的属性
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

      上述第7行代码在非严格模式下被忽略,在严格模式下报错。【注意】,①一旦使用 Object.defineProperty() 方法,如果没有指定特性的值,configurable、enumerable 和 writable 特性的默认值都是 false 【注意与在对象上定义属性时,特性的默认值不同】。②在 configurable 设置为 false 之前是可以多次调用 Object.defineProperty() 方法去设置同一个属性值的特性的,一旦 configurable 设置为 false 之后,就不允许在调用 Object.defineProperty() 方法去设置属性特性。严格模式下会报错。

    "use strict";
    let person = {};
    Object.defineProperty(person,"name",{
        writable: false,        
        value: "andy"
    });
    // 下一行代码报错,因为第三行方法中为 configurable 特性设置了 false 值。
    Object.defineProperty(person,"name",{
        value: "jack"
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

      或者使用 Object.defineProperties(obj, props) 一次定义多个新的属性或修改多个现有属性,并返回该对象。

    let obj = {};
    Object.defineProperties(obj, {
      'property1': {
        value: true,
        writable: true
      },
      'property2': {
        value: 'Hello',
        writable: false
      }
      // etc. etc.
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

      数据属性其实就是更加底层的设置属性的方法,可以对属性进行更加细微的设置,可以完全用数据属性的方法为一个对象设置相关属性。

    • 访问器属性

      访问器属性不包含数据值。它们包含一个获取 (getter) 函数和一个设置 (setter) 函数,不过这两个函数不是必需的。在读取访问器属性时,会调用获取函数,这个函数的责任就是返回一个有效的值。在写入访问器属性时,会调用设置函数并传入新值,这个函数必须决定对数据做出什么修改。访问器属性有 4 个特性描述它们的行为。

    ① [[Configurable]]:表示能否通过 delete 删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为数据属性。该特性的默认值都是 true。

    ② [[Enumerable]]:表示能否通过 for-in 循环返回属性。像前面例子中直接在对象上定义的属性,该特性的默认值都是 true。

    ③ [[Get]]:获取函数,在读取属性时调用。默认值为 undefined。

    ④ [[Set]]:设置函数,在写入属性时调用。默认值为 undefined。

      访问器属性是不能直接定义的,必须使用 Object.defineProperty()。下面是一个例子:

    let book = {
    	year_:2017,
    	edition:1
    };
    Object.defineProperty(book,"year",{
    	get() {
    		return this.year_;
    	},
    	set(newValue){
    		if(newValue > 2017){
    			this.year_ = newValue;
    			this.edition += newValue - 2017;
    		}
    	}
    });
    book.year = 2018;
    console.log(book.edition);	// 2
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

      获取函数和设置函数不一定都要定义。只定义获取函数意味着属性是只读的,尝试修改属性会被忽略。在严格模式下,尝试写入只定义了获取函数的属性会抛出错误。类似地,只有一个设置函数的属性是不能读取的,非严格模式下读取会返回 undefined,严格模式下会抛出错误。

      建议看完上面讲解再看一遍视频加深理解理解:Object.defineProperty

  • 相关阅读:
    【毕设教程】YOLOv7 目标检测网络解读
    15套前端经典实战项目大合集,小白练手必备实战项目
    公众号搜题查题接口 搜题公众号制作教程 附赠题库接口
    vue - vue基础/vue核心内容(终结篇)
    第7章 Redis的噩梦:阻塞
    【前端设计模式】之原型模式
    汽车车系查询易语言代码
    v-show和v-if指令的共同点和不同点
    我是如何组织 Go 代码的(目录结构 依赖注入 wire)
    [Err] 1093 - You can‘t specify target table ‘*****‘ for update in FROM clause
  • 原文地址:https://blog.csdn.net/ItDaChuang/article/details/127417064