70

いつ使うべきなのかしら

Object.defineProperty

オブジェクトの新しいプロパティを作成します。私は次のようなものを設定できることを知っています

enumerable: false

しかし、いつこれが本当に必要ですか?次のようなプロパティを設定した場合

myObject.myprop = 5;

その記述子はすべてtrueに設定されていますよね?.defineProperty()へのかなり冗長な呼び出しを使用するとき、そしてどのような理由で、私は実際にもっと興味があります。

4

10 に答える 10

48

Object.defineProperty主に、特定のプロパティ記述子(読み取り専用(定数)、列挙可能性(for (.. in ..)ループ、ゲッター、セッターにプロパティを表示しない)など)を使用してプロパティを設定するために使用されます。

"use strict";
var myObj = {}; // Create object
// Set property (+descriptor)
Object.defineProperty(myObj, 'myprop', {
    value: 5,
    writable: false
});
console.log(myObj.myprop);// 5
myObj.myprop = 1;         // In strict mode: TypeError: myObj.myprop is read-only

このメソッドはObject、プロパティを使用してプロトタイプを拡張します。ゲッターのみが定義され、列挙可能性はに設定されfalseます。

Object.defineProperty(Object.prototype, '__CLASS__', {
    get: function() {
        return Object.prototype.toString.call(this);
    },
    enumerable: false // = Default
});
Object.keys({});           // []
console.log([].__CLASS__); // "[object Array]"
于 2012-04-11T12:24:43.720 に答える
29

'enumerable'のような機能は、私の経験ではめったに使用されません。主なユースケースは、計算されたプロパティです。

var myObj = {};

myObj.width = 20;
myObj.height = 20;

Object.defineProperty(myObj, 'area', {
    get: function() {
        return this.width*this.height;
    }
});
console.log(myObj.area);
于 2014-01-10T13:23:53.663 に答える
18

Object.definePropertyを使用する本当に良い理由は、オブジェクト内の関数を計算されたプロパティとしてループできることです。これにより、関数の本体を返す代わりに関数が実行されます。

例えば:

var myObj = {};

myObj.width = 20;
myObj.height = 20;

Object.defineProperty(myObj, 'area', {
    get: function() {
        return this.width*this.height;
    },
    enumerable: true
});

for (var key in myObj) {
  if (myObj.hasOwnProperty(key)) {
    console.log(key + " -> " + myObj[key]);
  }
}
//width -> 20, height -> 20, area -> 400

関数をプロパティとしてオブジェクトリテラルに追加するのとは異なります。

var myObj = {};

myObj.width = 20;
myObj.height = 20;

myObj.area = function() {
       return this.width*this.height;
    };

for (var key in myObj) {
  if (myObj.hasOwnProperty(key)) {
    console.log(key + " -> " + myObj[key]);
  }
}
// width -> 20, height -> 20, area -> function() { return this.width*this.height;}

ループするために、列挙可能なプロパティをtrueに設定していることを確認してください。

于 2016-05-06T11:37:51.613 に答える
6

たとえば、 Vue.jsがオブジェクトの変更を追跡する方法は次のとおりdataです。

プレーンなJavaScriptオブジェクトをオプションとしてVueインスタンスに渡すとdata、Vueはそのすべてのプロパティをウォークスルーし、それらをgetter/settersusingに変換しますObject.defineProperty。これはES5のみでシミングできない機能であるため、VueはIE8以下をサポートしていません。

ゲッター/セッターはユーザーには見えませんが、内部では、プロパティがアクセスまたは変更されたときにVueが依存関係の追跡と変更通知を実行できるようにします。

[...]

Vue.jsの非常にスリムで基本的なバージョンでさえ、単なるもの以上のものを使用することに注意してくださいObject.defineProperty。ただし、主な機能はそれから来ています。

Vue.jsの反応性サイクル

ここでは、作成者がVue.jsのような最小限のPoCバージョンを実装している記事を見ることができます:https ://medium.com/js-dojo/understand-vue-reactivity-implementation-step-by-step-599c3d51cd6c

そしてここで、スピーカーがVue.jsで反応性を説明しながら同様の何かを構築するトーク(スペイン語):https ://www.youtube.com/watch?v = axXwWU-L7RM

于 2019-08-13T22:20:56.530 に答える
3

概要:

Javascriptでは、オブジェクトはキーと値のペアのコレクションです。 Object.defineProperty()オブジェクトに新しいプロパティを定義し、プロパティの次の属性を設定できる関数です。

  • value <any>キーに関連付けられた値
  • writable <boolean> writableがに設定されている場合trueプロパティに新しい値を割り当てることで、プロパティを更新できます。に設定されている場合false、値を変更することはできません。
  • enumerable <boolean> enumerableがPropertyに設定されている場合、ループtrueを介してアクセスできます。for..inさらに、で返される列挙可能なプロパティキーはこれだけです。Object.keys()
  • 構成可能<boolean>構成可能が設定されてfalseいる場合、プロパティ属性(値/書き込み可能/列挙可能/構成可能)の変更は変更できません。また、値は変更できないため、delete演算子を使用して削除することはできません。

例:

let obj = {};


Object.defineProperty(obj, 'prop1', {
      value: 1,
      writable: false,
      enumerable: false,
      configurable: false
});   // create a new property (key=prop1, value=1)


Object.defineProperty(obj, 'prop2', {
      value: 2,
      writable: true,
      enumerable: true,
      configurable: true
});  // create a new property (key=prop2, value=2)


console.log(obj.prop1, obj.prop2); // both props exists

for(const props in obj) {
  console.log(props);
  // only logs prop2 because writable is true in prop2 and false in prop1
}


obj.prop1 = 100;
obj.prop2 = 100;
console.log(obj.prop1, obj.prop2);
// only prop2 is changed because prop2 is writable, prop1 is not


delete obj.prop1;
delete obj.prop2;

console.log(obj.prop1, obj.prop2);
// only prop2 is deleted because prop2 is configurable and prop1 is not

于 2018-09-04T18:26:08.413 に答える
2

私が見た優れたユースケースの1つdefinePropertyは、ライブラリがユーザーにエラープロパティを提供することです。これは、特定の間隔内にアクセスされない場合、自分でエラーをログに記録します。例えば:

let logErrorTimeoutId = setTimeout(() => {
  if (error) {
    console.error('Unhandled (in <your library>)', error.stack || error);
  }
}, 10);

Object.defineProperty(data, 'error', {
    configurable: true,
    enumerable: true,
    get: () => {
      clearTimeout(logErrorTimeoutId);
      return error;
    },
  });

このコードのソース:https ://github.com/apollographql/react-apollo/blob/ddd3d8faabf135dca691d20ce8ab0bc24ccc414e/src/graphql.tsx#L510

于 2017-06-22T18:38:32.357 に答える
2

Object.defineProperty プロトタイプチェーンの一部のキーに誤って値を割り当てることを防ぎます。このメソッドでは、その特定のオブジェクトレベルにのみ割り当てます(プロトタイプチェーンのキーには割り当てません)。

例:次のようなオブジェクトがあり、{key1: value1, key2: value2}そのプロトタイプチェーンが正確にわからないか、誤ってそれを見逃し、プロトタイプチェーンのどこかにプロパティ「color」があります-

dot(。)割り当ての使用-

この操作により、プロトタイプチェーンのキー'color'に値が割り当てられ(キーがどこかに存在する場合)、変更なしでオブジェクトが見つかります。obj.color='青'; // objは{key1:value1、key2:value2}と同じままです

Object.definePropertyメソッドの使用-

Object.defineProperty(obj, 'color', {
  value: 'blue'
});

//objはのようになり{key1: value1, key2: value2, color: 'blue'}ます。同じレベルにプロパティを追加します。その後、メソッドを使用して安全に反復できますObject.hasOwnProperty()

于 2018-11-10T12:11:54.173 に答える
1

インターセプトを実行したり、従来のObserver/Observableパターンをエレガントな方法で適用したりする必要がある場合に適しています。

https://www.monterail.com/blog/2016/how-to-build-a-reactive-engine-in-javascript-part-1-observable-objects

于 2017-07-06T14:30:51.397 に答える
0

非常に便利なケースは、何かへの変更を監視し、それに基づいて行動することです。値が設定されるたびにコールバック関数を起動できるため、簡単です。これが基本的な例です。

Player再生中または非再生可能なオブジェクトがあります。再生を開始したときと、再生を停止したときに何かが発生するようにします。

function Player(){}
Object.defineProperty(Player.prototype, 'is_playing', {
  get(){
    return this.stored_is_playing;  // note: this.is_playing would result in an endless loop
  },
  set(newVal){
    this.stored_is_playing = newVal;
    if (newVal === true) {
      showPauseButton();
    } else {
      showPlayButton();
    }
  }
});
const cdplayer = new Player();
cdplayer.is_playing = true; // showPauseButton fires 

この回答は、ここにある他のいくつかの回答に関連しています。これらは、詳細情報の良いステップポイントですが、ライブラリやプログラミングパラダイムについて読むために外部リンクをたどる必要はありません。

于 2019-09-28T19:21:43.640 に答える
-2

@ジェラードシンプソン

'area'を列挙可能にする必要がある場合は、Object.definePropertyなしでも記述できます。

var myObj = {
    get area() { return this.width * this.height }
};

myObj.width = 20;
myObj.height = 20;

for (var key in myObj) {
  if (myObj.hasOwnProperty(key)) {
    console.log(key + " -> " + myObj[key]);
  }
}

//area -> 400, width -> 20, height -> 20
于 2016-12-11T11:22:29.720 に答える