JavaScriptの不思議なObject.definePropertyを詳しく説明します.

5525 ワード

ダイジェスト:JavaScriptには不思議なObject.definePropertyがあります.
=Object.definePropertyと
JavaScriptオブジェクトの属性を追加または変更するためには、直接的に使用するか、Object.defineProperty()を使用するかの2つの異なる方法があります.以下のとおりです
//   1
var obj = {};

//     =  
obj.a = 1;

//   Object.defineProperty  
Object.defineProperty(obj, "b",
{
    value: 2
});

console.log(obj) //   "{a: 1, b: 2}"
このように見れば、両者の違いはないようですね?しかし、Object.getOwn PropertyDescriptor()を使って、obj.aとobj.bの属性の記述記述子を見ると、=Object.defineProtyとは違っています.
//   2
var obj = {};

obj.a = 1;

Object.defineProperty(obj, "b",
{
    value: 2
});

console.log(Object.getOwnPropertyDescriptor(obj, "a")); //   "{value: 1, writable: true, enumerable: true, configurable: true}"
console.log(Object.getOwnPropertyDescriptor(obj, "b")); //   "{value: 2, writable: false, enumerable: false, configurable: false}"
属性記述子valueは、使用=赋値の場合は修正できますが、writable、enumerable、configrableはtrueです.
Object.definePropertyで定義されている属性の属性記述子writable、enumerable、configrableのデフォルト値はfalseですが、いずれも修正できます.writable、enumerable、configurbleの意味については、名前からは的中しにくく、後の文も詳しく紹介します.
使用=赋値は、Object.defineProperty()を使用して定義する場合と同等であり、同時にwritable、enumerable、configrableをtrueとする.コード例3と4は等価です.
//   3
var obj = {};

obj.name = "Fundebug";
console.log(Object.getOwnPropertyDescriptor(obj, "name")); //   {value: "Fundebug", writable: true, enumerable: true, configurable: true}
//   4
var obj = {};

Object.defineProperty(obj, "name",
{
    value: "Fundebug",
    writable: true,
    enumerable: true,
    configurable: true
});
console.log(Object.getOwnPropertyDescriptor(obj, "name")); //   {value: "Fundebug", writable: true, enumerable: true, configurable: true}
Object.defineProperty()
Object.defineProperty()を使用して定義する場合はvalueのみを定義すると、writable、enumerable、configrableのデフォルト値はfalseとなります.コード例5および6は等価である.
//   5
var obj = {};

Object.defineProperty(obj, "name",
{
    value: "Fundebug"
});
console.log(Object.getOwnPropertyDescriptor(obj, "name")); //   {value: "Fundebug", writable: false, enumerable: false, configurable: false}
//   6
var obj = {};

Object.defineProperty(obj, "name",
{
    value: "Fundebug",
    writable: false,
    enumerable: false,
    configurable: false
});
console.log(Object.getOwnPropertyDescriptor(obj, "name")); //   {value: "Fundebug", writable: false, enumerable: false, configurable: false}
writable、enumerableとconfigurbleは全部falseなので、obj.name属性は値を付けられなくて、遍歴できなくて、削除できません.
//   7
var obj = {};

Object.defineProperty(obj, "name",
{
    value: "Fundebug"
});

// writable false,    
obj.name = "  ";
console.log(obj.name); //   "Fundebug"

// enumerable false,    
console.log(Object.keys(obj)); //   "[]"

// configurable false,    
delete obj.name;
console.log(obj.name); //   "Fundebug"
厳密なモード(「use strict」)では、例7のコードはエラーとして報告されます.以下で見られます.
writable
writableがfalseの場合、属性は再割り当てできません.厳格なモードでは「Canot assign to read only property」とエラーが発生します.
//   8
"use strict"

var obj = {};

Object.defineProperty(obj, "name",
{
    value: "Fundebug",
    writable: false,
    enumerable: true,
    configurable: true
});

obj.name = "  "; //   “Uncaught TypeError: Cannot assign to read only property 'name' of object '#'”
writableがtrueの場合、属性は与えられます.この点は読者が自分でテストしてもいいです.
enumerable
enumerableがfalseの場合、属性は遍歴できません.
//   9
"use strict"

var obj = {};

Object.defineProperty(obj, "name",
{
    value: "Fundebug",
    writable: true,
    enumerable: false,
    configurable: true
});

console.log(Object.keys(obj)) //   "[]"
enumerableがtrueの時、属性は遍歴できます.この点は読者が自分でテストしてもいいです.
configrable
enumerableがfalseの場合、属性は削除できません.厳格なモードでは「Canot delete property」とエラーが発生します.
//   10
"use strict"

var obj = {};

Object.defineProperty(obj, "name",
{
    value: "Fundebug",
    writable: true,
    enumerable: true,
    configurable: false
});

delete obj.name //   “Uncaught TypeError: Cannot delete property 'name' of #
enumerableがtrueの場合、属性は削除できます.この点は読者が自分でテストしてもいいです.
writableとconfigrable
writableとenumerableが同時にfalseである場合、属性はObject.defineProperty()定義を再使用できなく、厳格なモードでは「Canot redefine property」をエラーする.
//   11
"use strict"

var obj = {};

Object.defineProperty(obj, "name",
{
    value: "Fundebug",
    writable: false,
    configurable: false
})

Object.defineProperty(obj, "name",
{
    value: "  "
}) //   “Uncaught TypeError: Cannot redefine property: name”
writableまたはenumerableがtrueである場合、属性はObject.defineProperty()定義を再利用できます.この点は読者が自分でテストしてもいいです.
本明細書のすべてのコード例は、Chrome 67でテストされる.
参照
  • Object.defineProperty()
  • Object.getOwn PropertyDescripter()
  • StockOverflow:Why can't I redefine a property in a Javascript Object?
  • Funebugについて
    FunndebugはJavaScript、微信小プログラム、微信小ゲーム、支付宝小プログラム、React Native、Node.js、JavaリアルタイムBUGの監視に専念しています.2016年双十一公式オンラインから、Fundebugは累計6億+エラーイベントを処理し、Google、360、金山軟件など多くの有名ユーザーに承認されました.無料試用を歓迎します.
    著作権声明
    転載する時、作者のFunebugと本文の住所を明記してください.https://blog.fundebug.com/2018/07/05/javascript-object-defineproperty/