Home  >  Article  >  Web Front-end  >  Introduction to the usage of Object.defineProperty in JS (code example)

Introduction to the usage of Object.defineProperty in JS (code example)

不言
不言forward
2019-03-15 17:12:212355browse

This article brings you an introduction to the usage of Object.defineProperty in JS (code examples). It has certain reference value. Friends in need can refer to it. I hope it will be helpful to you.

In JavaScript, the properties of an object are often added or modified through the following methods:

obj.name = 'John'

In addition, the properties of an object can also be added or modified through the Object.defineProperty() method . More importantly, in addition to the target object obj and the property name prop, the method can pass in the property descriptor descriptor to achieve more complex properties. An attribute descriptor is an object and has two forms: one is a data descriptor and the other is an access descriptor.

Object.defineProperty(obj, prop, descriptor)

Data descriptor

The data descriptor supports the following features:

enumerable: Indicates whether the object can be enumerated. The default is false, which means it cannot be enumerated. This property cannot be enumerated in for...in and Object.keys(), and it also affects JSON.stringify().

configurable: Indicates whether the object attributes can be deleted, and whether other attributes except value and writable attributes can be modified. The default is false, which means that the attribute cannot be deleted and the characteristics cannot be modified.

value: The value corresponding to the attribute, the default is undefined.

writable: The default is false, which means it is read-only and cannot assign a value to this property. In strict mode, assigning a value to a read-only property will result in an error. In relaxed mode, assigning values ​​to read-only properties will not take effect.

// 示例1,等同于 obj.name = 'John'
var obj = {}
Object.defineProperty(obj, 'name', { 
  value: 'John',
  writable: true,
  configerable: true,
  enumerable: true
})

// 示例2,将 name 属性设置为只读
'use strict'
var obj = {}
Object.defineProperty(obj, 'name', {
  value: 'John',
  writable: false,
  configerable: true,
  enumerable: true
})
obj.name = 'Joy'  // TypeError

// 示例3,将 name 属性设置为不可枚举
var obj = {}
Object.defineProperty(obj, 'name', { 
  value: 'John',
  writable: true,
  configerable: true,
  enumerable: false
})
console.log(obj.name)  // John
console.log(Object.keys(obj))  // []

// 示例4,将 name 属性设置不可配置(不可删除,除value和writable特性外的其它特性不可被修改)
var obj = {}
Object.defineProperty(obj, 'name', { 
  value: 'John',
  writable: true,
  configerable: false,
  enumerable: true
})
delete obj.name  // false
Object.defineProperty(obj, 'name', { enumerable: false })  // TypeError

Storage descriptor

Storage descriptor supports the following features:

enumerable: Same as above.

configurable: Same as above.

set: Set the setter method. When a property is modified, this method will be executed with the new property value as a parameter. The default value is undefined.

get: Set the getter method, which will be executed when the property is accessed. The default value is undefined.

// 示例5,使用 get 和 set,计数属性读写的次数
var obj = {}, name = '', count1 = 0, count2 = 0
Object.defineProperty(obj, 'name', { 
  get: function () { 
    console.log('Read ' + (++count1) + ' times')
    return name
  },
  set: function (newVal) {
    console.log('Write ' + (++count2) + ' times')
    name = newVal
  }
})
obj.name  // Read 1 times
obj['name']  // Read 2 times
obj.name = 'Joy'  // Write 1 times
obj.name = 'Jack'  // Write 2 times

Notes

In addition, there are three points to note. First, attributes with two different descriptors cannot be shared; second, when adding attributes, the unintroduced characteristics will be set to default values. , and when modifying the characteristics, the unintroduced characteristics remain the same; the third is as follows:

Object.defineProperty(obj, 'name', { value: 'John' })
// 属性是只读,不可配置,且不可枚举的。等同于
Object.defineProperty(obj, 'name', { 
  value: 'John',
  writable: false,
  configerable: false,
  enumerable: false
})

obj.name = 'John'
// 属性可写的,可配置的,可枚举的。等同于
Object.defineProperty(obj, 'name', { 
  value: 'John',
  writable: true,
  configerable: true,
  enumerable: true
})

Actual application

For example, there is an object Student, which has two attributes: name and age. If you do not want What should I do if the age is set too high or too low? We can add a setter and getter method. Every time we want to modify age, we can modify the attribute through the setter method and read the attribute through the getter method:

function Student (name, age) {
  this.name = name
  this.setAge = function (val) { 
    age = val
    if (age < 0) age = 0
    if (age > 100) age = 100
  }
  this.getAge = function () { return age }
}

var s = new Student('John', 16)
s.setAge(25)
console.log(s.getAge())  // 25
s.setAge(-5)
console.log(s.getAge())  // 0
s.setAge(500)
console.log(s.getAge())  // 100

It seems beautiful, but every time the attribute is read or modified The setter or getter method is called once, which adds a lot of code. Using the Object.defineProperty method, no extra code is needed, and the properties can be read and modified directly in the most primitive way:

function Student (name, age) {
  this.name = name
  var _age = age
  Object.defineProperty(this, 'age', {
    get: function () { return _age },
    set: function (val) {
      _age = val
      if (_age < 0) _age = 0
      if (_age > 100) _age = 100
    }
  })
}

var s = new Student('John', 16)
s.age = 25
console.log(s.age)  // 25
s.age = -5
console.log(s.age)  // 0
s.age = 500
console.log(s.age)  // 100

Batch processing

The Object.defineProperties() method can be added or modified in batches Properties:

var obj = {}
Object.defineProperties(obj, {
  name: { value: 'John', emunerable: true },
  age: { value: 20, emunerable: true }
})

The Object.create() method can add properties in batches when creating an object:

var obj = Object.create(Object.prototype, {
  name: { value: 'John', emunerable: true },
  age: { value: 20, emunerable: true } 
})

You can also create objects containing setter and getter properties through literals:

var obj = {
  get name() {
    return 'John'
  },
  set name(val) {
    console.log(val)
  },
  get age() {
    return 18
  }
}

The above is the detailed content of Introduction to the usage of Object.defineProperty in JS (code example). For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:segmentfault.com. If there is any infringement, please contact admin@php.cn delete