JavaScript — Property Descriptor && PropertyDescriptor (ok)

https://codeburst.io/javascript-object-property-attributes-ac012be317e2

JavaScript — Property Descriptor

In this article, we will learn writable, enumerable and configurable attributes of the property and use of getters and setters.

Trong bài này, chúng ta sẽ tìm hiểu các thuộc tính có thể ghi, có thể liệt kê và có thể định cấu hình của thuộc tính và cách sử dụng getters và setters.

Property Descriptor

Every object property is more than just a name and value pair. Each property is having property descriptor that helps to see all the attributes of that property.

Mọi thuộc tính đối tượng không chỉ là một cặp têngiá trị. Mỗi thuộc tính có bộ mô tả thuộc tính giúp xem tất cả các thuộc tính của thuộc tính đó.

var bike = {
  name: 'SuperSport', 
  maker: 'Ducati', 
  engine: '937cc'
};console.log(Object.getOwnPropertyDescriptor(bike, 'engine'));//Output will be below object
{
  configurable: true,
  enumerable: true,
  value: "937cc",
  writable: true
}

In the above code snippet, we are logging all the attributes of property engine of object bike using method getOwnPropertyDescriptor(). So, we can see that addition to the value attribute, it has three more attributes (configurable, enumerable and writable). All these are true by default.

Trong đoạn mã trên, chúng ta đang ghi lại tất cả các thuộc tính của thuộc tính engine của object bike bằng phương thức getOwnPropertyDescriptor (). Vì vậy, chúng ta có thể thấy rằng ngoài thuộc tính giá trị, nó có thêm ba thuộc tính (có thể định cấu hình, có thể liệt kê và có thể ghi). Tất cả những điều này đều đúng theo mặc định.

Let’s understand all the attributes one by one.

Hãy hiểu từng thuộc tính một.

writable attribute

Writable attribute decides whether the value associated with the property can be changed or not, from its initial value. we can modify the property attributes using method Object.defineProperty() like below

Thuộc tính ghi quyết định liệu giá trị được liên kết với thuộc tính có thể được thay đổi hay không, từ giá trị ban đầu của nó. chúng ta có thể sửa đổi các thuộc tính thuộc tính bằng phương thức Object.defineProperty () như bên dưới

var bike = {
  name: 'SuperSport', 
  maker:'Ducati', 
  engine:'937cc'
};
Object.defineProperty(bike, 'engine', {writable: false});bike.engine = '2000cc';
// Throws error in strict mode
// Uncaught TypeError: Cannot assign to read only propertyconsole.log(bike.engine);
// Output will be 937cc in non-strict mode

In the above code snippet, we can see that writable attribute of property engine modified to false means we made it non-writable. Then if we try to change the value of engine property, it throws error saying “TypeError: Cannot assign to read only property”. But error shows only if the code is executed in strict mode otherwise it silently fails and value of engine property does not get updated. So bike.engine still prints its original value in case of non-strict mode.

Trong đoạn mã trên, chúng ta có thể thấy rằng thuộc tính có thể ghi của công cụ thuộc tính được sửa đổi thành false có nghĩa là chúng tôi đã đặt nó thành không thể ghi. Sau đó, nếu chúng tôi cố gắng thay đổi giá trị của thuộc tính engine, nó sẽ báo lỗi “TypeError: Không thể gán cho thuộc tính chỉ đọc”. Nhưng lỗi chỉ hiển thị nếu mã được thực thi ở chế độ nghiêm ngặt, nếu không, nó sẽ âm thầm bị lỗi và giá trị của thuộc tính động cơ không được cập nhật. Vì vậy bike.engine vẫn in giá trị ban đầu của nó trong trường hợp chế độ không nghiêm ngặt.

Let’s go through one more example to understand the interesting part of writable property. If the non-writable property itself is an object then we can modify the property of that object. In the below code snippet, property engine is now an object and assigning new value to bike.engine.cc is allowed. It means only modifying the engine property itself is not allowed but properties of engine can be changed.

Hãy xem qua một ví dụ nữa để hiểu phần thú vị của thuộc tính có thể ghi. Nếu bản thân thuộc tính không thể ghi là một đối tượng thì chúng ta có thể sửa đổi thuộc tính của đối tượng đó. Trong đoạn mã bên dưới, thuộc tính engine hiện là một đối tượng và cho phép gán giá trị mới cho bike.engine.cc. Nó có nghĩa là không được phép sửa đổi bản thân thuộc tính engine nhưng các thuộc tính của engine có thể được thay đổi.

'use strict';
var bike = {
  name: 'SuperSport', 
  maker:'Ducati', 
  engine:{cc: '937', type: 'petrol'}
};Object.defineProperty(bike, 'engine', {writable: false});bike.engine.cc = '950';
console.log(bike.engine);//Output will be
{
  cc: "950",
  type: "petrol"
}

If we still want to make the object to be non-writable completely along with its properties then we can use the method Object.freeze() as shown below

Nếu chúng ta vẫn muốn làm cho đối tượng hoàn toàn không thể ghi cùng với các thuộc tính của nó thì chúng ta có thể sử dụng phương thức Object.freeze () như hình dưới đây

var bike = {
  name: 'SuperSport', 
  maker:'Ducati', 
  engine:{cc: '937', type: 'petrol'}
};Object.defineProperty(bike, 'engine', {writable: false});
Object.freeze(bike.engine);bike.engine.cc = '950';
// Throws error in strict modeconsole.log(bike.engine.cc); 
// Output will be 937 in non-strict mode

Object.defineProperty() is capable of adding new property on an object as well along with modifying an existing property.

Object.defineProperty () có khả năng thêm thuộc tính mới trên một đối tượng cũng như sửa đổi thuộc tính hiện có.

enumerable attribute

By default, properties of any object are enumerable means we can loop over them. But the default behavior can be modified by setting enumerable attribute to false for that property as shown below

Theo mặc định, các thuộc tính của bất kỳ đối tượng nào đều có thể liệt kê được nghĩa là chúng ta có thể lặp lại chúng. Nhưng hành vi mặc định có thể được sửa đổi bằng cách đặt thuộc tính enumerable thành false cho thuộc tính đó như được hiển thị bên dưới

var bike = {
  name: 'SuperSport', 
  maker:'Ducati', 
  engine: {cc: '937', type: 'petrol'}
};
Object.defineProperty(bike, 'maker', {enumerable: false});
for(let propName in bike) {
  console.log(propName);
}
// Output:   name engine  (property maker is missing)
var keys = Object.keys(bike);
console.log(keys);
// Output:   ["name", "engine"] (property maker is missing)

In the above code snippet, Object.keys() method returns an array of a given object’s own enumerable properties but it only enumerates name and engine property and skipped the maker property because enumerable attribute of property maker is set to false.

Trong đoạn mã trên, phương thức Object.keys () trả về một mảng các thuộc tính có thể liệt kê của một đối tượng nhất định nhưng nó chỉ liệt kê thuộc tính tên và công cụ và bỏ qua thuộc tính maker vì thuộc tính enumerable của thuộc tính được đặt thành false.

for..in loop helps to traverse through entire object.

configurable attribute

We can configure all the attributes of the object. But if we set configurable attribute to false, it prevents certain attributes being changed and prevents the deletion of the property itself.

Chúng ta có thể cấu hình tất cả các thuộc tính của đối tượng. Nhưng nếu chúng ta đặt thuộc tính có thể định cấu hình thành false, thì nó sẽ ngăn một số thuộc tính bị thay đổi và ngăn việc xóa chính thuộc tính đó.

var bike = {
  name: 'SuperSport', 
  maker: 'Ducati', 
  engine: '937cc'
};
Object.defineProperty(bike, 'name', {configurable: false});
Object.defineProperty(bike, 'name', {enumerable: false});
// TypeError: Cannot redefine property: name
Object.defineProperty(bike, 'name', {writable: false});
// No error
Object.defineProperty(bike, 'name', {configurable: true});
// Throws error
delete bike.name;
// TypeError: Cannot delete property 'name' (strict mode only)

As per the above code snippet, we can see that once configurable attribute is set to false .It does not allow to modify the enumerable and configurable attribute but it does allow to change writable attribute and we can not delete the property as well if configurable attribute is set to false. (we need to remove the first error statement to see the later errors in console because execution stops once it hits first error in the code)

Theo đoạn mã trên, chúng ta có thể thấy rằng một khi thuộc tính có thể định cấu hình được đặt thành sai. Nó không cho phép sửa đổi thuộc tính có thể định cấu hình và liệt kê nhưng nó cho phép thay đổi thuộc tính có thể ghi và chúng tôi cũng không thể xóa thuộc tính nếu thuộc tính có thể định cấu hình được đặt thành false. (chúng tôi cần xóa câu lệnh lỗi đầu tiên để xem các lỗi sau đó trong bảng điều khiển vì quá trình thực thi sẽ dừng lại khi nó gặp lỗi đầu tiên trong mã)

All attributes can be modified in a single statement of Object.defineProperty() as well like below without any error.

Tất cả các thuộc tính có thể được sửa đổi trong một câu lệnh duy nhất của Object.defineProperty () cũng như bên dưới mà không có bất kỳ lỗi nào

var bike = {
  name: 'SuperSport', 
  maker: 'Ducati', 
  engine: '937cc'
};
Object.defineProperty(bike, 'name', {
  configurable: false,
  writable: false,
  enumerable: false,
  value: '1000cc'
});

get and set attributes

Attributes get and set are functions which works as getter and setter respectively for the property. When the property is accessed, get function gets called without any arguments and when the property is assigned with some value then set function gets called with the value assigned to the property. To create getter and setter, we need to use method Object.defineProperty() as specified below

Các thuộc tính get và set là các hàm hoạt động như getter và setter tương ứng cho thuộc tính. Khi thuộc tính được truy cập, hàm get được gọi mà không có bất kỳ đối số nào và khi thuộc tính được gán với một số giá trị thì hàm set sẽ được gọi với giá trị được gán cho thuộc tính. Để tạo getter và setter, chúng ta cần sử dụng phương thức Object.defineProperty () như được chỉ định bên dưới

var fuel = 'petrol';
var car = {
  name: 'SuperFast', 
  maker: 'Ferrari', 
  engine: 'v12'
};
Object.defineProperty(car, 'engineDetails', {
  get: function() {
    return fuel +" "+ this.engine + " engine";
  },
  set: function(details) {
    let splits = details.split(' ');
    fuel = splits[0];
    this.engine = splits[1];
  }
});
console.log(car.engineDetails);   // output: petrol v12 engine
car.engineDetails = "diesel v8";
console.log(car.engineDetails);   // output: diesel v8 engine

In the above code snippet, engineDetails is a new property to the object car which is having get and set attributes defined. We can still able to access the property like any other property even though behind the scene it actually executes the function get and set. So, we can see that getter and setter are very powerful because we can do lot more things apart from normal retrieve and assignment operation.

Trong đoạn mã trên, engineDetails là một thuộc tính mới của object car đang có các thuộc tính get và set được xác định. Chúng ta vẫn có thể truy cập thuộc tính như bất kỳ thuộc tính nào khác mặc dù đằng sau cảnh đó thực sự thực thi hàm get và set. Vì vậy, chúng ta có thể thấy rằng getter và setter rất mạnh mẽ vì chúng ta có thể làm được nhiều việc hơn ngoài thao tác truy xuất và gán thông thường.

In the above code, the keyword this is execution context object . To understand how keyword this works in details, you can go through my article JavaScript — All about this and new keyword .

Trong đoạn mã trên, từ khóa đây là đối tượng ngữ cảnh thực thi. Để hiểu chi tiết cách thức hoạt động của từ khóa này, bạn có thể xem qua bài viết của tôi JavaScript - Tất cả về từ khóa này và từ khóa mới.

Summary

We learned all about the JavaScript Object Property Attributes. Starting with property descriptor. Next, we learned use of writable, enumerable and configurable attribute. Finally understood the power of get and set attribute.

Chúng tôi đã tìm hiểu tất cả về Thuộc tính thuộc tính đối tượng JavaScript. Bắt đầu với bộ mô tả thuộc tính. Tiếp theo, chúng ta đã học cách sử dụng thuộc tính có thể ghi, có thể liệt kê và có thể định cấu hình. Cuối cùng đã hiểu được sức mạnh của thuộc tính get và set.

If you like this post and it was helpful, please click the clap 👏 button multiple times to show support, thank you.

Last updated

Navigation

Lionel

@Copyright 2023