TIL coding
  • Initial page
  • 排版
  • Flexbox
  • Grid
  • jQuery
  • Untitled
  • JavaScript
    • An Introduction to JavaScript
    • Hello, world!
    • Code structure
    • The modern mode, "use strict"
    • Variables
    • Data types
    • Type Conversions
    • Operators
    • Comparisons
    • Interaction: alert, prompt, confirm
    • Conditional operators: if, '?'
    • Logical operators
    • Loops: while and for
    • The "switch" statement
    • Functions
    • Function expressions and arrows
    • JavaScript specials
    • Comments
    • Ninja code
    • Automated testing with mocha
    • Polyfills
    • Objects
    • Garbage collection
    • Symbol type
    • Object methods, "this"
    • Object to primitive conversion
    • Constructor, operator "new"
    • Methods of primitives
    • Numbers
    • Strings
    • Arrays
    • Array methods
    • Iterables
    • Map, Set, WeakMap and WeakSet
    • Object.keys, values, entries
    • Destructuring assignment
    • Date and time
    • JSON methods, toJSON
    • Recursion and stack
    • Rest parameters and spread operator
    • Closure
    • The old "var"
    • Global object
    • Function object, NFE
    • The "new Function" syntax
    • Scheduling: setTimeout and setInterval
    • Decorators and forwarding, call/apply
    • Function binding
    • Currying and partials
    • Arrow functions revisited
    • Property flags and descriptors
    • Property getters and setters
    • Prototypal inheritance
    • F.prototype
    • Native prototypes
    • Prototype methods, objects without __proto__
    • The “class” syntax
    • Class inheritance
    • Static properties and methods
    • Private and protected properties and methods
    • Extending built-in classes
    • Class checking: "instanceof"
    • Mixins
    • Error handling, "try..catch"
    • Custom errors, extending Error
    • Introduction: callbacks
    • Promise
    • Promises chaining
    • Error handling with promises
    • Promise API
  • Bootstrap
    • Navbar
Powered by GitBook
On this page
  • Property flags
  • Read-only
  • Non-enumerable
  • Non-configurable
  • Object.defineProperties
  • Object.getOwnPropertyDescriptors

Was this helpful?

  1. JavaScript

Property flags and descriptors

Property flags

屬性除了值還有 3 個標誌,創造屬性時不會看到他們,因為預設皆為 true。

  • writable – if true, can be changed, otherwise it’s read-only.

  • enumerable – if true, then listed in loops, otherwise not listed.

  • configurable – if true, the property can be deleted and these attributes can be modified, otherwise not.

// Object.getOwnPropertyDescriptor() 可以完整取得屬性的資訊
let descriptor = Object.getOwnPropertyDescriptor(obj, propertyName);

let user = {
  name: "John"
};

let descriptor = Object.getOwnPropertyDescriptor(user, 'name');

alert( JSON.stringify(descriptor, null, 2 ) );
/* property descriptor:
{
  "value": "John",
  "writable": true,
  "enumerable": true,
  "configurable": true
}
*/

// Object.defineProperty() 可以改變屬性的標誌
Object.defineProperty(obj, propertyName, descriptor)

// 屬性存在會改變標誌,屬性不存在會創造,但標誌皆為 false
let user = {};

Object.defineProperty(user, "name", {
  value: "John"
});

let descriptor = Object.getOwnPropertyDescriptor(user, 'name');

alert( JSON.stringify(descriptor, null, 2 ) );
/*
{
  "value": "John",
  "writable": false,
  "enumerable": false,
  "configurable": false
}
 */

Read-only

// writable: false 不可修改
let user = {
  name: "John"
};

Object.defineProperty(user, "name", {
  writable: false
});

user.name = "Pete"; // Error: Cannot assign to read only property 'name'...

// 對新增的屬性要列出標誌的值,不然皆為 false
let user = { };

Object.defineProperty(user, "name", {
  value: "Pete",
  // for new properties need to explicitly list what's true
  enumerable: true,
  configurable: true
});

alert(user.name); // Pete
user.name = "Alice"; // Error

Non-enumerable

// 內建的 toString 不會顯示在迴圈,但自定義的 toString 會出現在迴圈
let user = {
  name: "John",
  toString() {
    return this.name;
  }
};

// 默认情况下,我们的两个属性都会列出:
for (let key in user) alert(key); // name, toString

// enumerable: false toString 不會出現在迴圈
let user = {
  name: "John",
  toString() {
    return this.name;
  }
};

Object.defineProperty(user, "toString", {
  enumerable: false
});

// Now our toString disappears:
for (let key in user) alert(key); // name

// 也不會出現在 Object.keys()
alert(Object.keys(user)); // name

Non-configurable

// configurable: false 不能藉由 Object.defineProperty() 刪除或修改屬性
let descriptor = Object.getOwnPropertyDescriptor(Math, 'PI');

alert( JSON.stringify(descriptor, null, 2 ) );
/*
{
  "value": 3.141592653589793,
  "writable": false,
  "enumerable": false,
  "configurable": false
}
*/

// 不能刪除屬性
Math.PI = 3; // Error
// delete Math.PI won't work either

// configurable: false 沒有回頭路,會鎖住所有屬性資訊無法更改
let user = { };

Object.defineProperty(user, "name", {
  value: "John",
  writable: false,
  configurable: false
});

// won't be able to change user.name or its flags
// all this won't work:
//   user.name = "Pete"
//   delete user.name
//   defineProperty(user, "name", ...)
Object.defineProperty(user, "name", {writable: true}); // Error

Object.defineProperties

// syntax
Object.defineProperties(obj, {
  prop1: descriptor1,
  prop2: descriptor2
  // ...
});

// example
Object.defineProperties(user, {
  name: { value: "John", writable: false },
  surname: { value: "Smith", writable: false },
  // ...
});

Object.getOwnPropertyDescriptors

// 可以用迴圈複製物件
for (let key in user) {
  clone[key] = user[key]
}

// 用 Object.getOwnPropertyDescriptors() + Object.defineProperties() 式更好的方法
// 可以複製所有屬性的資訊
let clone = Object.defineProperties({}, Object.getOwnPropertyDescriptors(obj));
PreviousArrow functions revisitedNextProperty getters and setters

Last updated 5 years ago

Was this helpful?