js--对象内部属性与 Object.defineProperty |

js--对象内部属性与 Object.defineProperty |

前言

JavaScript 中允许使用一些内部特性来描述属性的特征,本文来总结一下对象内部属性与 Object.defineProperty() 的相关知识。

正文

  1、属性类型

  js中使用某些内部属性来描述属性的特征,比如描述属性是否可以枚举,是否可以修改等特征,我们无法访直接问属性的这些特征,但是可以通过[[]]的方式来将某个特性标识为内部属性。这些内部属性分为数据属性和访问器属性。

  (1)数据属性

  数据属性包含一个保存数据值的位置。值会从这个位置读取,也会写入到这个位置。数据属性有 4个特性描述它们的行为。

  a、[[Configurable]]表示能否通过 delete 删除属性从而重新定义属性,能否修改属性的特性,或者能否把数据属性修改为访问器属性,默认 true。

  b、[[Enumerable]]表示能否通过 for-in 循环遍历出属性 默认 true。

  c、[[Writable]]表示能否修改属性的值,默认 true,设置为 false 指改属性只读。

  d、[[Value]]保存这个属性的数据值,读写属性的值都是在这个位置,默认值为 undefined。

  要修改对象默认数据属性,必须使用es5的 Object.defineProperty(),该方法包含三个参数,给其添加属性的对象、属性的名称和一个描述符对象。如下:

    var person = {};    Object.defineProperty(person, "age", {      enumerable: true,      configurable: false,      value: 18    });    console.log(person.age);// 18    delete person.age    console.log(person.age);// 18    Object.defineProperty(person, "height", {      enumerable: false,      value: 50    });    console.log(person);//{age:18,height:50}    for (const key in person) {      console.log(key, person[key]);// age 18    }    Object.defineProperty(person, "name", {      writable: false,      value: "Nicholas"    });    console.log(person.name); // "Nicholas"    person.name = "Greg";    console.log(person.name); // "Nicholas"

  注意:在调用 Object.defineProperty() 时, configurable 、 enumerable 和 writable 的值如果不指定,则都默认为 false 。

  (2)访问器属性

  访问器属性 ==访问器属性不包含数据值,他们包含setter和getter函数,这两个函数并不是必须的

  a、[[Configurable]]表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或者能否把数据属性修改为访问器属性,默认 true。

  b、[[Enumerable]]表示能否通过for-in循环遍历出属性 默认 true。

  c、[[Set]]写入属性的函数,默认 undefined。

  d、[[Get]]读取属性的函数,默认 undefined。

  同样,访问器属性是不能直接定义的,必须使用 Object.defineProperty() 。如下:

    var person = { name: "Nicholas", isAdult: true };    Object.defineProperty(person, 'age', {      get: function () {        return this.age      },      set: function (newValue) {        this.isAdult = newValue >= 18 ? true : false      }    });    console.log(person.isAdult);    person.age = 17    console.log(person.isAdult);

  注意:设置了访问器属性之后不能再设置数据属性,比如设置了 set/get 就不能再设置 writable。

  2、补充:内部属性的操作

  (1)一次性定义多个属性

  ECMAScript 提供了 Object.defineProperties() 方法可以通过多个描述符一次性定义多个属性。它接收两个参数:要为之添加或修改属性的对象和另一个描述符对象,其属性与要添加或修改的属性一一对应。这样所有属性都是同时定义的,并且数据属性的configurable 、 enumerable 和 writable 特性值都是 false。
    var person = {}    Object.defineProperties(person, {      'name': {        value: "Nicholas"      },      'isAdult': {        writable: true,        configurable: true,        value: true      },      'age': {        configurable: true,        get() {          return this.age        },        set(newValue) {          this.isAdult = newValue >= 18 ? true : false        }      }    })    console.log(person.isAdult);// true    person.age = 17// 首先到age的set方法,然后访问isAdult的writable属性并修改value值    console.log(person.isAdult);// false

  (2)读取属性的特性 Object.getOwnPropertyDescriptor()获取传入对象给定属性的描述符。Object.getOwnPropertyDescriptors()获取给定对象的全部属性描述符。

    var person = { name: "Nicholas", isAdult: true };    Object.defineProperty(person, 'age', {      get: function () {        return this.age      },      set: function (newValue) {        this.isAdult = newValue >= 18 ? true : false      }    });    var descriptor = Object.getOwnPropertyDescriptor(person, 'age')    console.log(descriptor);    //configurable: false    // enumerable: false    // get: ƒ ()    // set: ƒ (newValue)    console.log(Object.getOwnPropertyDescriptors(person));    // {name:{...},isAdult:{...},age:{...}}

  3、对象内部特性和 Object.defineProperty() 应用

  (1)手写实现 const

    function myConst(key, value) {      window.key = value // 把要定义的key挂载到window下,并赋值value      Object.defineProperty(window, key, {        enumerable: false,        configurable: false,        get: function () {          return value        },        set: function (data) {          if (data !== value) { // 当要对当前属性进行赋值时,则抛出错误            throw new TypeError('Assignment to constant variable.')          } else {            return value          }        }      })    }    myConst('a', 2)    console.log(a);    a = 3//报错 :Assignment to constant variable.

  (2)手动实现每次访问一个属性时,值加一,使得a==1&&a==2&a==3成为可能

    window.b = 0    Object.defineProperty(window, "a", {      get() {        this.b++        return this.b      },      set(value) {        this.b = value      }    })    if (a == 1 && a == 2 & a == 3) {      console.log("111");    }//111

写在最后

  以上就是本文的全部内容,希望给读者带来些许的帮助和进步,方便的话点个关注,小白的成长之路会持续更新一些工作中常见的问题和技术点。



免责声明:本网信息来自于互联网,目的在于传递更多信息,并不代表本网赞同其观点。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,并请自行核实相关内容。本站不承担此类作品侵权行为的直接责任及连带责任。如若本网有任何内容侵犯您的权益,请及时联系我们,本站将会在24小时内处理完毕。
相关文章
返回顶部