कई जावास्क्रिप्ट वस्तुओं से गुणों को कैसे बदलना है


105

मैं कई जावास्क्रिप्ट ऑब्जेक्ट्स (साहचर्य सरणियों) को "जोड़ने" का सबसे अच्छा तरीका ढूंढ रहा हूं।

उदाहरण के लिए, दिया गया:

a = { "one" : 1, "two" : 2 };
b = { "three" : 3 };
c = { "four" : 4, "five" : 5 };

गणना करने का सबसे अच्छा तरीका क्या है:

{ "one" : 1, "two" : 2, "three" : 3, "four" : 4, "five" : 5 }

3
एक शब्दार्थ नोट: [] वाक्य रचना के बावजूद, वे बिल्कुल भी सरणियाँ नहीं हैं। आदेश वास्तव में गारंटी नहीं है।
अल्वारो गोंजालेज

1
प्रतिमान मानकों के अनुसार Iteration आदेश की गारंटी नहीं है। लेकिन यह अधिकांश ब्राउज़रों में इसे लागू करने का तरीका है। (जॉन रेसिग से) यह व्यवहार स्पष्ट रूप से ECMAScript विनिर्देश द्वारा अपरिभाषित है। ECMA-262 में, खंड 12.6.4: गुणों की गणना करने वाले यांत्रिकी ... कार्यान्वयन निर्भर है। हालांकि, विनिर्देश कार्यान्वयन से काफी अलग है। ECMAScript के सभी आधुनिक कार्यान्वयन वस्तु गुणों के माध्यम से उस क्रम में पुनरावृत्ति करते हैं जिसमें वे परिभाषित किए गए थे। इस वजह से क्रोम टीम ने इसे बग माना है और इसे ठीक किया जाएगा।
जुआन मेंडेस

जवाबों:


159

ECMAscript 6 ने Object.assign()जावास्क्रिप्ट में इसे मूल रूप से प्राप्त करने के लिए पेश किया।

Object.assign () विधि लक्ष्य वस्तु के लिए एक या अधिक स्रोत वस्तुओं से सभी गणनीय खुद गुण के मूल्यों की प्रतिलिपि करने के लिए किया जाता है। यह लक्ष्य वस्तु को लौटा देगा।

Object.assign पर MDN प्रलेखन ()

var o1 = { a: 1 };
var o2 = { b: 2 };
var o3 = { c: 3 };

var obj = Object.assign({}, o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }

Object.assignकई आधुनिक ब्राउज़रों में समर्थित है, लेकिन अभी तक उनमें से सभी नहीं हैं। की तरह एक transpiler का प्रयोग करें कोलाहल और Traceur पीछे की ओर संगत ES5 जावास्क्रिप्ट उत्पन्न करने के लिए।


4
यह सबसे अच्छा मैं कह सकता है। चूंकि E6 अब ज्यादातर इस्तेमाल किया जाता है, Object.assign सबसे अच्छा जवाब है।
विमलराज सेल्वम

6
यदि आप नहीं जानते हैं कि कितनी वस्तुओं को मर्ज करने की आवश्यकता है, तो मान लें कि वे एक सरणी में हैं आप उन्हें निम्न प्रकार से मर्ज कर सकते हैं:Object.assign.apply({}, [{a: 1}, {b: 2}, ....])
जीनलूका स्कल्जेरी

1
उपयोग का एक विकल्प Object.assign.apply: ऑब्जेक्ट की श्रृंखला मर्ज करने के लिए, बजाय प्रसार ऑपरेटर का उपयोग करने के लिए हैObject.assign( ...objects )
Spen

@ इस प्रश्न के उत्तर के रूप में पहले से ही शामिल है। मुझे यहाँ इसे नक़ल करने का कोई फ़ायदा नहीं हुआ।
15

4 घंटे के बाद, इस जवाब ने मेरी समस्या को 7 कोणीय में हल कर दिया। उत्तर की सरलता और सटीकता के लिए धन्यवाद।
जेल

35

आप $.extendइस तरह से jquery का उपयोग कर सकते हैं :

let a = { "one" : 1, "two" : 2 },
    b = { "three" : 3 },
    c = { "four" : 4, "five" : 5 };

let d = $.extend({}, a, b, c)

console.log(d)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>


+1 यदि आप jQuery की विधि का उपयोग नहीं करते हैं, तो आप अपने स्वयं के (शायद, अधिक विशिष्ट) कार्यान्वयन के निर्माण में मदद करने के लिए उनके कोड का उपयोग कर सकते हैं।
tvanfosson

25
@ रैंडल: jQuery का उपयोग नहीं करने के कई पूरी तरह से अच्छे कारण हैं।
टिम डाउन

3
संपादित करें:d = $.extend({},a,b,c);
बॉब स्टीन

34

यह करना चाहिए:

function collect() {
  var ret = {};
  var len = arguments.length;
  for (var i = 0; i < len; i++) {
    for (p in arguments[i]) {
      if (arguments[i].hasOwnProperty(p)) {
        ret[p] = arguments[i][p];
      }
    }
  }
  return ret;
}

let a = { "one" : 1, "two" : 2 };
let b = { "three" : 3 };
let c = { "four" : 4, "five" : 5 };

let d = collect(a, b, c);
console.log(d);

आउटपुट:

{
  "one": 1,
  "two": 2,
  "three": 3,
  "four": 4,
  "five": 5
}

lengthप्रत्येक आह्वान पर सरणी का आकार नहीं देखता है? मुझे लिखने की आदत है for (var i = 0, len = array.length; i < len; ++i)कि मैं अपने सिर के ऊपर से याद नहीं कर सकता कि मैंने ऐसा क्यों करना शुरू किया।
tvanfosson

1
हाँ, यह सही है। एक बार लंबाई को कैश करने के लिए बेहतर प्रदर्शन है। हालाँकि, क्योंकि तर्कों का आकार "सरणी" कभी बहुत बड़ा होने की संभावना नहीं है, यह वास्तव में इस मामले में मायने नहीं रखेगा।
jhurshman

1
नहीं, IE6 पर थोड़ा छोड़कर। लंबाई की संपत्ति तक पहुँचने के लिए लेन चर तक पहुँचने के समान ही खर्च होता है।
एलसिंकेड

1
@ जुआन मुझे लगता है कि आप गलत हैं, और मैंने अपने दिमाग को बनाने के लिए कुछ परीक्षण किए। लंबाई का कैशिंग अनुकूलन का एक आसान मिथक है जो कई वर्षों से अप्रचलित है, और यह कोड (थोड़ा) को कम पठनीय बनाता है। दरअसल, लंबाई को कैशिंग करने से कभी-कभी ब्राउज़र (सफारी) धीमा हो जाता है।
Alsciende

2
क्या इसके लिए '(var p in ...' के बजाय 'for (p ... in') लिखना बेहतर नहीं होगा?
ह्यूगो


12

ऐसा करने के लिए अंडरस्कोर के कुछ तरीके हैं;

1. _ . अगला (गंतव्य, * स्रोत)

गंतव्य ऑब्जेक्ट पर स्रोत ऑब्जेक्ट में सभी गुणों की प्रतिलिपि बनाएँ , और गंतव्य ऑब्जेक्ट वापस करें ।

_.extend(a, _.extend(b, c));
=> {"one" : 1, "two" : 2, "three" : 3, "four" : 4, "five" : 5 }

या

_.extend(a, b);
=> {"one" : 1, "two" : 2, "three" : 3}
_.extend(a, c);
=> {"one" : 1, "two" : 2, "three" : 3, "four" : 4, "five" : 5 }

2. _ . दोष (वस्तु, * चूक)

डिफ़ॉल्ट ऑब्जेक्ट्स से मानों के साथ ऑब्जेक्ट में अपरिभाषित गुणों को भरें , और ऑब्जेक्ट को वापस करें ।

_.defaults(a, _.defaults(b, c));
=> {"one" : 1, "two" : 2, "three" : 3, "four" : 4, "five" : 5 }

या

_.defaults(a, b);
=> {"one" : 1, "two" : 2, "three" : 3}
_.defaults(a, c);
=> {"one" : 1, "two" : 2, "three" : 3, "four" : 4, "five" : 5 }

4

फ़ंक्शन को 3 तर्कों तक सीमित क्यों रखा जाना चाहिए? इसके अलावा जांच करें hasOwnProperty

function Collect() {
    var o={};
    for(var i=0;i<arguments.length;i++) {
      var arg=arguments[i];
      if(typeof arg != "object") continue;
      for(var p in arg) {
        if(arg.hasOwnProperty(p)) o[p] = arg[p];
      }
    }
    return o;
}

4

उथला-क्लोनिंग (प्रोटोटाइप को छोड़कर) या ऑब्जेक्ट्स को मर्ज करना अब Object.assign () की तुलना में छोटे सिंटैक्स का उपयोग करना संभव है ।

ECMAScript 2018 में वस्तु शाब्दिकों के लिए प्रसार सिंटैक्स पेश किया गया था:

const a = { "one": 1, "two": 2 };
const b = { "three": 3 };
const c = { "four": 4, "five": 5 };

const result = {...a, ...b, ...c};
// Object { "one": 1, "two": 2 , "three": 3, "four": 4, "five": 5 }

स्प्रेड (...) ऑपरेटर कई आधुनिक ब्राउज़रों में समर्थित है, लेकिन उनमें से सभी नहीं।

इसलिए, यह एक का उपयोग करने की सलाह देते है transpiler तरह कोलाहल वर्तमान और पुराने ब्राउज़र या वातावरण में जावास्क्रिप्ट का एक पीछे की ओर संगत संस्करण में ECMAScript 2015+ कोड कन्वर्ट करने के लिए।

यह बबल कोड आपके लिए जनरेट करेगा :

"use strict";

var _extends = Object.assign || function(target) {
  for (var i = 1; i < arguments.length; i++) {
    var source = arguments[i];
    for (var key in source) {
      if (Object.prototype.hasOwnProperty.call(source, key)) {
        target[key] = source[key];
      }
    }
  }
  return target;
};

var a = { "one": 1, "two": 2 };
var b = { "three": 3 };
var c = { "four": 4, "five": 5 };

var result = _extends({}, a, b, c);
// Object { "one": 1, "two": 2 , "three": 3, "four": 4, "five": 5 }

यह स्वीकृत उत्तर की तुलना में अधिक मजबूत उत्तर है। धन्यवाद!
कालेब एंडरसन

3
function Collect(a, b, c) {
    for (property in b)
        a[property] = b[property];

    for (property in c)
        a[property] = c[property];

    return a;
}

सूचना: पिछली वस्तुओं में विद्यमान संपत्तियों को अधिलेखित कर दिया जाएगा।


2
इसका साइड-इफेक्ट है कि a === dअंत में। यह ठीक हो सकता है और यह नहीं हो सकता है।
tvanfosson

2

आपके ब्राउज़र कंसोल में किसी ऑब्जेक्ट के लिए ES7 स्प्रेड ऑपरेटर का उपयोग करना आसान है

({ name: "Alex", ...(true  ? { age: 19 } : { })}) // {name: "Alex", age: 19}
({ name: "Alex", ...(false ? { age: 19 } : { })}) // {name: "Alex",        }

1
अच्छा लगा। यह सवाल 10 साल से अधिक पुराना है, खुशी है कि इस तरह के सरल ऑपरेशन अब आसान हैं। यदि आप अन्य लोगों के उत्तरों को देखते हैं तो यह पहले आसान नहीं था।
व्लाद

इसलिए मैंने अपना जवाब छोड़ दिया :)
Purkhalo Alex

2

वस्तुओं की एक गतिशील संख्या को मर्ज करने के लिए, हम प्रसार सिंटैक्स केObject.assign साथ उपयोग कर सकते हैं ।

const mergeObjs = (...objs) => Object.assign({}, ...objs);

उपरोक्त फ़ंक्शन किसी भी संख्या में ऑब्जेक्ट्स को स्वीकार करता है, अपने सभी गुणों को एक नई ऑब्जेक्ट में गुणों के साथ विलय करता है, जो बाद की वस्तुओं से पिछली वस्तुओं से ओवरराइटिंग करता है।

डेमो:

ऑब्जेक्ट की एक सरणी को मर्ज करने के लिए, एक समान विधि लागू की जा सकती है।

const mergeArrayOfObjs = arr => Object.assign({}, ...arr);

डेमो:


1

संभवतः, सबसे तेज़, कुशल और अधिक सामान्य तरीका यह है (आप किसी भी संख्या में वस्तुओं को मर्ज कर सकते हैं और यहां तक ​​कि पहले वाले को कॉपी कर सकते हैं -> असाइन करें):

function object_merge(){
    for (var i=1; i<arguments.length; i++)
       for (var a in arguments[i])
         arguments[0][a] = arguments[i][a];
   return arguments[0];
}

यह आपको पहली वस्तु को संशोधित करने की भी अनुमति देता है क्योंकि यह संदर्भ से गुजरती है। यदि आप यह नहीं चाहते हैं, लेकिन सभी गुणों से युक्त एक पूरी तरह से नई वस्तु रखना चाहते हैं, तो आप पहले तर्क के रूप में {} पास कर सकते हैं।

var object1={a:1,b:2};
var object2={c:3,d:4};
var object3={d:5,e:6};
var combined_object=object_merge(object1,object2,object3); 

संयुक्त_बजेक्ट और ऑब्जेक्ट 1 दोनों में ऑब्जेक्ट 1, ऑब्जेक्ट 2, ऑब्जेक्ट 3 के गुण होते हैं।

var object1={a:1,b:2};
var object2={c:3,d:4};
var object3={d:5,e:6};
var combined_object=object_merge({},object1,object2,object3); 

इस स्थिति में, संयुक्त_बजेक्ट में ऑब्जेक्ट 1, ऑब्जेक्ट 2, ऑब्जेक्ट 3 के गुण होते हैं लेकिन ऑब्जेक्ट 1 को संशोधित नहीं किया जाता है।

यहां देखें: https://jsfiddle.net/ppwovxey/1/

नोट: जावास्क्रिप्ट ऑब्जेक्ट्स संदर्भ द्वारा पारित किए जाते हैं।


1

ES6 ++

प्रश्न विभिन्न विभिन्न वस्तुओं को एक में जोड़ रहा है।

let obj = {};
const obj1 = { foo: 'bar' };
const obj2 = { bar: 'foo' };
Object.assign(obj, obj1, obj2);
//output => {foo: 'bar', bar: 'foo'};

मान लें कि आपके पास ऑब्जेक्ट्स वाली कई कुंजियों के साथ एक ऑब्जेक्ट है:

let obj = {
  foo: { bar: 'foo' },
  bar: { foo: 'bar' }
}

यह वह समाधान था जो मैंने पाया (अभी भी इसके लिए है: /)

let objAll = {};

Object.values(obj).forEach(o => {
  objAll = {...objAll, ...o};
});

ऐसा करने से हम गतिशील रूप से सभी ऑब्जेक्ट कुंजियों को एक में जोड़ सकते हैं।

// Output => { bar: 'foo', foo: 'bar' }


हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.