既存のオブジェクトに分解することは可能ですか?(Javascript ES6)


135

たとえば、2つのオブジェクトがあるとします。

var foo = {
  x: "bar",
  y: "baz"
}

そして

var oof = {}

そして、xとyの値をfooからoofに転送したかったのです。es6構造化構文を使用してそれを行う方法はありますか?

おそらく次のようなもの:

oof{x,y} = foo

10
すべてのプロパティをコピーする場合Object.assign(oof, foo)
elclanrs '14

ここMDNでの破壊的な例がたくさんありますが、あなたが質問している例はわかりません。
jfriend00

うーん、私は...どちらかを見つけることができませんでした
majorBummer

なしの2行ソリューションについては、以下の私の回答を参照してくださいObject.assign
Zfalen

回答:


115

醜いと少し繰り返しながら、行うことができます

({x: oof.x, y: oof.y} = foo);

これは、fooオブジェクトの2つの値を読み取り、それらをoofオブジェクトのそれぞれの場所に書き込みます。

個人的にはまだ読んだほうがいい

oof.x = foo.x;
oof.y = foo.y;

または

['x', 'y'].forEach(prop => oof[prop] = foo[prop]);

でも。


2
代替['x'、 'y']。forEach(prop => oof [prop] = foo [prop]); 私が見るように、これまで唯一のDRY(自分自身を繰り返さないでください)です。「DRY」は、複数のキーをマップする場合に実際に役立ちます。1つの場所を更新するだけで済みます。多分私は間違っています。とにかくありがとう!
Vladimir Brasil

1
3番目の例はDRYですが、文字列をキーとして使用する必要があります。これは通常、JavaScriptが暗黙的に実行します。次の場合よりも迷惑ではないと確信できません。const{x、y} = foo; const oof = {x、y};
Jeff Lowery 2017年

最初の提案が機能するjsfiddleで誰かが私を表示できますか?ここではChromeで機能
techguy2000

@ techguy2000後にセミコロンを忘れましたvar oof = {};
loganfsmyth 2017

最初のコードでは、({x: oof.x, y: oof.y} = foo)?あなたは余分なfを入れたと思います OOFを
Sornii 2018

38

いいえ、構造化では省略表現のメンバー式はサポートされていませんが、現時点ではプレーンプロパティ名のみがサポートされています。esdiscussでそのようなことについてのがありましたが、提案はES6にそれを作ることはありません。

Object.assignただし、使用できる場合があります。独自のプロパティがすべて必要ない場合でも、引き続き使用できます。

var foo = …,
    oof = {};
{
    let {x, y} = foo;
    Object.assign(oof, {x, y})
}

3
@loganfsmyth、あなたの例は、少なくともノード4.2.2での私のテストでは機能しません。--harmony_destructuring有効。「SyntaxError:Unexpected token」が表示されます。
jpierson 2016

@loganfsmythこれは非常に便利なコメントimoであるため、適切な回答を送信する必要があります。
サリワイン

@サリウェイン:彼はそうしました(今)。Bergiは、おそらくLoganが示すようにメンバー式を使用できることを示すために回答を更新するのが最善でしょう。(2015年4月から6月にかけて仕様が大幅に変更されたことは本当に本当ですか?)
TJクローダー

@TJCrowderいいえ、私はそれが変わったとは思いません、私が話していたと思います{oof.x, oof.y} = foo。それとも私は本当にそれを逃したのかもしれません。
ベルギ

29

IMOこれはあなたが探しているものを達成する最も簡単な方法です:

let { prop1, prop2, prop3 } = someObject;
let data = { prop1, prop2, prop3 };

  // data === { prop1: someObject.prop1, ... }

基本的には、変数に分解し、初期化子の省略形を使用して新しいオブジェクトを作成します。の必要はありませんObject.assign

とにかく、これが最も読みやすい方法だと思います。これによりsomeObject、必要な小道具を正確に選択できます。プロップをマージしたい既存のオブジェクトがある場合は、次のようにします。

let { prop1, prop2, prop3 } = someObject;
let data = Object.assign(otherObject, { prop1, prop2, prop3 });
    // Makes a new copy, or...
Object.assign(otherObject, { prop1, prop2, prop3 });
    // Merges into otherObject

それを書くもう一つの、間違いなくよりクリーンな方法は:

let { prop1, prop2, prop3 } = someObject;
let newObject = { prop1, prop2, prop3 };

// Merges your selected props into otherObject
Object.assign(otherObject, newObject);

私はこれをPOST数個の個別のデータだけが必要なリクエストによく使用します。しかし、私はこれを行うための1つのライナーがあるべきであることに同意します。

編集:PS- 私は最近、複雑なオブジェクトからネストされた値を引き出すために、最初のステップで超構造化を使用できることを学びました!例えば...

let { prop1, 
      prop2: { somethingDeeper }, 
      prop3: { 
         nested1: {
            nested2
         } 
      } = someObject;
let data = { prop1, somethingDeeper, nested2 };

さらに、新しいオブジェクトを作成するときにObject.assignの代わりにspread演算子を使用できます。

const { prop1, prop2, prop3 } = someObject;
let finalObject = {...otherObject, prop1, prop2, prop3 };

または...

const { prop1, prop2, prop3 } = someObject;
const intermediateObject = { prop1, prop2, prop3 };
const finalObject = {...otherObject, ...intermediateObject };

私はこのアプローチが実用的です。
ジェシー

2
これは私がすることですが、あまり乾燥していません。多くの人が本当に必要としているのは、キーの抽出機能だけだと思います。
jgmjgm 2018年

@jgmjgmええ、それを組み込んでおくのはいいことですが、私もそれを書くのはそれほど難しくないと思います。
Zfalen

12

他よりもObject.assignそこにあるオブジェクトのスプレッド構文はECMAScriptのためのステージ2の提案です。

var foo = {
  x: "bar",
  y: "baz"
}

var oof = { z: "z" }

oof =  {...oof, ...foo }

console.log(oof)

/* result 
{
  "x": "bar",
  "y": "baz",
  "z": "z"
}
*/

ただし、この機能を使用するには、Babelのプラグインstage-2またはtransform-object-rest-spreadプラグインを使用する必要があります。ここにバベルのデモがありますstage-2


9
これは実際には既存のオブジェクトのプロパティを設定するのではなく、両方のすべてのプロパティを含む新しいオブジェクトを作成します。
Matt Browne 2017年

8

BabelJSプラグイン

BabelJSを使用している場合は、プラグインをアクティブ化できますbabel-plugin-transform-object-from-destructuringインストールと使用方法については、npmパッケージを参照してください))。

このスレッドで説明したのと同じ問題があり、構造化式からオブジェクトを作成するとき、特にプロパティの名前を変更、追加、または削除する必要があるときは、非常に疲れました。このプラグインを使用すると、このようなシナリオを維持することがはるかに簡単になります。

オブジェクトの例

let myObject = {
  test1: "stringTest1",
  test2: "stringTest2",
  test3: "stringTest3"
};
let { test1, test3 } = myObject,
  myTest = { test1, test3 };

次のように書くことができます:

let myTest = { test1, test3 } = myObject;

配列の例

let myArray = ["stringTest1", "stringTest2", "stringTest3"];
let [ test1, , test3 ] = myArray,
  myTest = [ test1, test3 ];

次のように書くことができます:

let myTest = [ test1, , test3 ] = myArray;

これがまさに私が欲しかったものです。ありがとうございました!
21

let myTest = { test1, test3 } = myObject;が機能しない
Eatdoku


3

次のように再構築を使用できます。

const foo = {x:"a", y:"b"};
const {...oof} = foo; // {x:"a", y:"b"} 

または、oofに値がある場合は両方のオブジェクトをマージします。

const foo = {x:"a", y:"b"};
let oof = {z:"c"}
oof = Object.assign({}, oof, foo)

この最初のケースはまさに私が探していたものだと思います。Chromeコンソールで試してみましたが、動作しているようです。乾杯!@campsafari
majorBummer

1
@majorBummer最後にあなたの呼び出しですが、タイトルのように既存のオブジェクトにプロパティを追加するのではなく、どちらも新しいオブジェクトを作成するため、実際には質問に答えないアプローチを検討します。
loganfsmyth

@loganfsmythは良い点です。それが可能であることに気付いていなかったので、campSafariが持ち出した方法に興奮しただけだと思います。
majorBummer

1
新しいオブジェクトを作成してもかまわない場合は、次のようにしてくださいoof = {...oof, ...foo}
Joshua Coady

2

アロー関数で非構造化オブジェクトを返し、Object.assign()を使用してそれを変数に割り当てることができます。

const foo = {
  x: "bar",
  y: "baz"
}

const oof = Object.assign({}, () => ({ x, y } = foo));

1

ドライ

var a = {a1:1, a2: 2, a3: 3};
var b = {b1:1, b2: 2, b3: 3};

const newVar = (() => ({a1, a2, b1, b2})).bind({...a, ...b});
const val = newVar();
console.log({...val});
// print: Object { a1: 1, a2: 2, b1: 1, b2: 2 }

または

console.log({...(() => ({a1, a2, b1, b2})).bind({...a, ...b})()});

1

別のオブジェクト属性に直接割り当てるオブジェクトを破棄できます。

作業例:

let user = {};
[user.name, user.username] = "Stack Overflow".split(' ');
document.write(`
1st attr: ${user.name} <br /> 
2nd attr: ${user.username}`);

キャッチしたいオブジェクト属性と同じ名前の変数を使用して、デストラクタを操作できます。これにより、次の操作を行う必要がなくなります。

let user = { name: 'Mike' }
let { name: name } = user;

この方法を使用します。

let user = { name: 'Mike' }
let { name } = user;

同じ方法で、同じ名前のオブジェクト構造に新しい値を設定できます。

この実用的な例を見てください:

// The object to be destructed
let options = {
  title: "Menu",
  width: 100,
  height: 200
};

// Destructing
let {width: w, height: h, title} = options;

// Feedback
document.write(title + "<br />");  // Menu
document.write(w + "<br />");      // 100
document.write(h);                 // 200


0

これはChrome 53.0.2785.89で動作します

let foo = {
  x: "bar",
  y: "baz"
};

let oof = {x, y} = foo;

console.log(`oof: ${JSON.stringify(oof)});

//prints
oof: {
  "x": "bar",
  "y": "baz"
}

7
悲しいことに、それは(少なくともChromeでは)oof参照foo全体を受け取り、全体の構造化を迂回しているようです。oof === fooそしてlet oof = { x } = foo、まだ戻って{ x, y }
Theo.T

@ Theo.T良いキャッチ。それは残念です、私は別の方法を見つける必要があります
user1577390

これは、JSがどのように混乱する可能性があるかを示すためだけに保持する価値があります。
jgmjgm 2018年

0

私はこの方法を思いつきました:

exports.pick = function pick(src, props, dest={}) {
    return Object.keys(props).reduce((d,p) => {
        if(typeof props[p] === 'string') {
            d[props[p]] = src[p];
        } else if(props[p]) {
            d[p] = src[p];
        }
        return d;
    },dest);
};

次のように使用できます:

let cbEvents = util.pick(this.props.events, {onFocus:1,onBlur:1,onCheck:'onChange'});
let wrapEvents = util.pick(this.props.events, {onMouseEnter:1,onMouseLeave:1});

つまり、必要なプロパティを選択して、新しいオブジェクトに配置できます。_.pickあなたとは異なり、それらの名前を同時に変更することもできます。

プロップを既存のオブジェクトにコピーする場合は、dest引数を設定するだけです。


0

これは一種の不正行為ですが、次のようなことができます...

const originalObject = {
  hello: 'nurse',
  meaningOfLife: 42,
  your: 'mom',
};

const partialObject = (({ hello, your }) => {
  return { hello, your };
})(originalObject);

console.log(partialObject); // ​​​​​{ hello: 'nurse', your: 'mom' }​​​​​

実際には、それを使用することはめったにありません。以下はより明確です...しかし、それほど楽しくはありません。

const partialObject = {
  hello: originalObject.hello,
  your: originalObject.your,
};

プロトタイプをいじくることを含む別の完全に異なるルート(今は注意してください...):

if (!Object.prototype.pluck) {
  Object.prototype.pluck = function(...props) {
    return props.reduce((destObj, prop) => {
      destObj[prop] = this[prop];

      return destObj;
    }, {});
  }
}

const originalObject = {
  hello: 'nurse',
  meaningOfLife: 42,
  your: 'mom',
};

const partialObject2 = originalObject.pluck('hello', 'your');

console.log(partialObject2); // { hello: 'nurse', your: 'mom' }

0

これは私が思いつくことができる最も読みやすく、最も短い解決策です:

let props = { 
  isValidDate: 'yes',
  badProp: 'no!',
};

let { isValidDate } = props;
let newProps = { isValidDate };

console.log(newProps);

出力されます { isValidDate: 'yes' }

いつの日かこのようなことを言うことができればいいのですlet newProps = ({ isValidDate } = props)が、残念ながらそれはES6がサポートするものではありません。


0

それは美しい方法ではありませんし、私もお勧めしませんが、知識のためだけに、この方法は可能です。

const myObject = {
  name: 'foo',
  surname: 'bar',
  year: 2018
};

const newObject = ['name', 'surname'].reduce(
  (prev, curr) => (prev[curr] = myObject[curr], prev),
  {},
);

console.log(JSON.stringify(newObject)); // {"name":"foo","surname":"bar"}

0

JSONクラスのメソッドを使用して、次のように実現できます。

const foo = {
   x: "bar",
   y: "baz"
};

const oof = JSON.parse(JSON.stringify(foo, ['x','y']));
// output -> {x: "bar", y: "baz"}

結果のオブジェクトに追加する必要があるプロパティをstringify、配列形式で機能する2番目の引数として渡します。

JSON.stringifyのMDNドキュメント

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.