जावास्क्रिप्ट ऑब्जेक्ट विशेषताओं का डिफ़ॉल्ट मान सेट करें


83

क्या किसी जावास्क्रिप्ट ऑब्जेक्ट की डिफ़ॉल्ट विशेषता सेट करने का एक तरीका ऐसा है:

var emptyObj = {};
// do some magic
emptyObj.nonExistingAttribute // => defaultValue

आईई की अवहेलना की जा सकती है, क्रोम फ्रेम ने मुझे उस सिरदर्द से छुटकारा दिलाया है।


हर मौजूदा गैर-मौजूदा विशेषता या सिर्फ एक विशेषता नाम?
— js1568

जवाबों:


120

चूंकि मैंने कई साल पहले सवाल पूछा था कि चीजें अच्छी तरह से आगे बढ़ चुकी हैं।

प्रॉक्सी ES6 का हिस्सा हैं। निम्न उदाहरण क्रोम, फ़ायरफ़ॉक्स, सफारी और एज में काम करता है :

var handler = {
  get: function(target, name) {
    return target.hasOwnProperty(name) ? target[name] : 42;
  }
};

var p = new Proxy({}, handler);

p.answerToTheUltimateQuestionOfLife; //=> 42

प्रॉक्सी पर मोज़िला के दस्तावेज़ में और पढ़ें ।


यदि आप इंटरनेट एक्सप्लोरर (एज से पहले) का समर्थन करने की योजना बना रहे हैं, तो आप भाग्य से बाहर हैं: caniuse.com/#search=proxy इसके अलावा, polyfill github.com/tvcutsem/harmony-reflect IE का समर्थन नहीं करता है
— Tiagojdfernira

21
बधाई हो, आपने फीनिक्स (गोल्ड बैज) अर्जित किया है : कम से कम एक साल बाद अपने स्वयं के प्रश्नों में से एक का उत्तर दिया, इस उत्तर के साथ कि कम से कम सबसे लोकप्रिय उत्तर के वोटों की संख्या दोगुनी हो गई)
— जिग्गी

Object.withDefault = (defaultValue, o = {}) => नया प्रॉक्सी (o, {get: (o, k) => (o में k)? O [k]: defaultValue}); ओ = Object.withDefault (42); बैल // => 42 बैल = 10 बैल // => 10 o.xx // => 42
— व्लाद वी

इसलिए प्रॉक्सी का उपयोग करने का अर्थ यह भी Object.getEntriesनहीं हो सकता है कि प्रॉक्सी पर कॉल किया जा सकता है :(
— मेरेडिथ

1
यदि आप मतलब रखते हैं Object.entries, तो आप हैंडलर को संपत्तियों को सेट करने के लिए संशोधित कर सकते हैं जब वे एक्सेस किए जाते हैं। बदलें return target.hasOwnProperty(name) ? target[name] : 42;करने के लिए if (!target.hasOwnProperty(name)) target[name] = 42; return target[name];।
— डॉसेंटरमैटर

31

विनाशकारी का उपयोग करें (ES6 में नया)

मोज़िला द्वारा महान प्रलेखन के साथ-साथ एक शानदार ब्लॉग पोस्ट है जो सिंटैक्स को मुझसे बेहतर बताता है।

तुम्हारे प्रश्न का उत्तर देने के लिए

var emptyObj = {};
const { nonExistingAttribute = defaultValue } = emptyObj;
console.log(nonExistingAttribute); // defaultValue

आगे बढ़ते हुए

क्या मैं इस चर का नाम बदल सकता हूं ? ज़रूर!

const { nonExistingAttribute: coolerName = 15} = emptyObj;
console.log(coolerName); // 15

नेस्टेड डेटा के बारे में क्या? जो है सामने रखो!

var nestedData = {
    name: 'Awesome Programmer',
    languages: [
        {
            name: 'javascript',
            proficiency: 4,
        }
    ],
    country: 'Canada',
};

var {name: realName, languages: [{name: languageName}]} = nestedData ;

console.log(realName); // Awesome Programmer
console.log(languageName); // javascript

28

इसे जावास्क्रिप्ट में सेट करने का कोई तरीका नहीं है - undefinedगैर-मौजूद गुणों के लिए लौटना कोर जावास्क्रिप्ट स्क्रिप्ट का एक हिस्सा है। इसी तरह के सवाल के लिए चर्चा देखें । जैसा कि मैंने वहां सुझाव दिया, एक दृष्टिकोण (हालांकि मैं वास्तव में इसकी सिफारिश नहीं कर सकता) एक वैश्विक getPropertyसमारोह को परिभाषित करना होगा :

function getProperty(o, prop) {
    if (o[prop] !== undefined) return o[prop];
    else return "my default";
}

var o = {
    foo: 1
};

getProperty(o, 'foo'); // 1
getProperty(o, 'bar'); // "my default"

लेकिन यह गैर-मानक कोड का एक समूह होगा जो दूसरों के लिए पढ़ना मुश्किल होगा, और यह उन क्षेत्रों में अनपेक्षित परिणाम हो सकता है जहां आप उम्मीद करते हैं या एक अपरिभाषित मूल्य चाहते हैं। बेहतर है कि आप जाते ही जाँच करें:

var someVar = o.someVar || "my default";

10
चेतावनी: var someVar = o.someVar || "my default";संभावित रूप से अप्रत्याशित परिणाम होंगे जब o.someVar पॉपुलेटेड होता है लेकिन गलत (उदा।, 0, "") का मूल्यांकन करता है। someVar = o.someVar === undefined ? o.someVar : "my default";बेहतर होगा। मैं आमतौर पर ||अकेले का उपयोग करता हूं जब डिफ़ॉल्ट भी false. (e.g. o.someVar का मूल्यांकन करता है || 0`)
— शनीमल

5
यह एक अच्छा बिंदु है - यह कहीं भी काम नहीं करेगा जहां एक गलत-वाई मान मान्य इनपुट है, और आपको इस पैटर्न का उपयोग करते समय विचार करना होगा। लेकिन अधिक बार नहीं, यह एक संपत्ति को स्पष्ट रूप से nullया falseउसी तरह से सेट करने के लिए समझ में आता है , जिस स्थिति में यह दोहरी ड्यूटी करता है। चेतावनी उचित है, यद्यपि।
— nrabinowitz

5
@ शनीमल आपका उदाहरण गलत तरीका है, यह someVar = o.someVar === undefined ? "my default" : o.someVar;केवल एक छोटी सी समस्या होनी चाहिए , लेकिन जब मैंने पहली बार आपके कोड को
— आज़माया

हां @ मेटल्सकिन हम अपरिभाषित मूल्य की परवाह नहीं करेंगे? जबरदस्त हंसी। क्षमा करें, उम्मीद है कि गलती से आपका बहुत अधिक समय खर्च नहीं हुआ :)
— Shanimal

11

यह सुनिश्चित होता है कि प्रोटिओपे-आधारित वस्तुओं का विशिष्ट उपयोग होता है:

// define a new type of object
var foo = function() {};  

// define a default attribute and value that all objects of this type will have
foo.prototype.attribute1 = "defaultValue1";  

// create a new object of my type
var emptyObj = new foo();
console.log(emptyObj.attribute1);       // outputs defaultValue1

यदि आप कंसोल.लॉग (रिक्त स्थिति) कहते हैं, तो यह {} वापस आ जाता है। नहीं {attribute1: 'defaultValue1'}
— Throrin19

2
हां, क्योंकि attribute1: defaultValue1प्रोटोटाइप और कंसोल पर है। केवल शीर्ष स्तर ऑब्जेक्ट पर सेट किए गए आइटमों को एनरोमेट करता है, प्रोटोटाइप पर नहीं। लेकिन, मूल्य वहाँ मेरे console.log(emptyObj.attribute1)शो के रूप में है ।
— jfriend00

यह सही है लेकिन इसके साथ भी यही समस्या है JSON.stringify(emptyobj)। मुझे एक ऐसी विधि बनाने के लिए मजबूर किया गया था जो इस समस्या के जवाब में सभी विशेषताओं को
— लौटाती

11

मेरा कोड है:

function(s){
    s = {
        top: s.top || 100,    // default value or s.top
        left: s.left || 300,  // default value or s.left
    }
    alert(s.top)
}

1
मुझे यह समाधान सबसे अच्छा लगता है, क्योंकि यह PHP में मेरे द्वारा किए जाने वाले समान है। function foo( array $kwargs = array() ) { // Fill in defaults for optional keyworded arguments. $kwargs += array( 'show_user' => true, 'show_links' => false, ); ...
— माइक फिंच

10

जिस तरह से मैं इसे प्राप्त करता हूं वह object.assignफ़ंक्शन के साथ है

const defaultProperties = { 'foo': 'bar', 'bar': 'foo' };
const overwriteProperties = { 'foo': 'foo' };
const newObj = Object.assign({}, defaultProperties, overwriteProperties);
console.log(defaultProperties);  // {"foo": "bar", "bar": "foo"}
console.log(overwriteProperties);  // { "foo": "foo" };
console.log(newObj);  // { "foo": "foo", "bar": "foo" }

5
ऐसा करने से आप overwritePropertiesसही तरीके के मूल्यों को भी लिख रहे हैं :const newObj = Object.assign({}, defaultProperties, overwriteProperties)
— फ्रांसिस्को पुगा

6

मुझे लगता है कि सबसे सरल दृष्टिकोण का उपयोग कर रहा है Object.assign।

यदि आपके पास यह वर्ग है:

class MyHelper {
    constructor(options) {
        this.options = Object.assign({
            name: "John",
            surname: "Doe",
            birthDate: "1980-08-08"
        }, options);
    }
}

आप इसे इस तरह से उपयोग कर सकते हैं:

let helper = new MyHelper({ name: "Mark" });
console.log(helper.options.surname); // this will output "Doe"

प्रलेखन (पॉलीफ़िल के साथ): https://developer.mozilla.org/it/docs/Web/JavaScript/Reference/Global_Objects/Object/assign


6

सभी समाधानों में सबसे सरल:

dict = {'first': 1,
        'second': 2,
        'third': 3}

अभी,

dict['last'] || 'Excluded'

'बहिष्कृत' लौटाएगा, जो कि डिफ़ॉल्ट मान है।


3
यह विफल रहता है यदि आपके पास थोड़ा अलग तानाशाही है:dict = {'first': 0, 'second': 1, 'third': 2}
— व्लाद वी

2
यह श्रृंखला मानों का एक शानदार तरीका है जो मौजूद नहीं हो सकता है। उदाहरण के लिए a.b.c.d। यदि एक, डी, या सी अपरिभाषित हैं, तो आप एक त्रुटि मारते हैं, लेकिन आप बस कर सकते हैं(((a || {}).b || {}).c || {}).d) || "default"
— hobberwickey

1
अब तक का सबसे अच्छा समाधान!
— आर्थर हार्डुइम

5

या आप यह कोशिश कर सकते हैं

dict = {
 'somekey': 'somevalue'
};

val = dict['anotherkey'] || 'anotherval';

15
बुरा विचार अगर तानाशाह ['एक और' हो तो 0. है
— रे तोल

शायद आपको इस पर विचार करना चाहिए: codereadability.com/…
— ebragaparah

@RayToal तब वह String()ठीक नहीं होगा ? जैसे:val = dict[String('anotherkey')] || 'anotherval';
— गॉडस्टाइम ओसारबो

नहीं, क्षमा करें, यह नहीं होगा। एक ही समस्या है। इसे आज़माएं: पहले करें और d = {x: 1, y: 0}फिर d['y'] || 100इसे गलत तरीके से न दें। 100. फिर अपने विचार को आज़माएं d[String('y')] || 100- यह अभी भी अनुचित रूप से 100 देता है जब इसे 0. देना चाहिए
— रे तोल

4

यह मुझे ऐसा करने का सबसे सरल और पठनीय तरीका लगता है:

let options = {name:"James"}
const default_options = {name:"John", surname:"Doe"}

options = Object.assign({}, default_options, options)

Object.assign () संदर्भ


मैं जवाब देने जा रहा था कि अंडरस्कोर लाइब्रेरी के लिए _.defaults (ऑब्जेक्ट, * डिफॉल्ट्स) विधि है, लेकिन आपका जवाब बिना किसी लाइब्रेरी के ही मिलता है!
— दानीसी

2

मैंने कल एक लेख देखा जिसमें एक Object.__noSuchMethod__संपत्ति का उल्लेख है: जावास्क्रिप्टटिप्स मुझे इसके साथ खेलने का मौका नहीं मिला है, इसलिए मुझे ब्राउज़र समर्थन के बारे में नहीं पता है, लेकिन शायद आप किसी तरह से इसका उपयोग कर सकते हैं?


उस पृष्ठ को भी देखा, हम एक ही HN लेख पढ़ा होगा। हालांकि केवल तरीके। यह डिफाइनगेटर के साथ किया जा सकता है लेकिन दुर्भाग्य से ECMA5 में नहीं है। वे एक अन्य गेट्टर / सेटर दृष्टिकोण के साथ नहीं हैं जो मेरे विचार में बदतर है (पहले से गुणों की परिभाषा की आवश्यकता है)।
— सैंडस्ट्रॉम

यह भविष्य में एक उत्तर हो सकता है :) चलो आशा करते हैं कि ब्राउज़र जल्द ही मिल जाएंगे :)
— j

1
मुझे विश्वास है कि भविष्य का उत्तर
— जेम्स लॉन्ग

@JamesLong हाँ, आप सही हैं! पता चला कि भविष्य आ गया है :) 3 साल बाद मैंने सवाल पूछा कि यह अब एफएफ (और अन्य ब्राउज़रों में जल्द ही) काम करता है। मैंने नीचे एक उत्तर जोड़ा है।
— सैंडस्ट्रॉम

2

मुझे आश्चर्य है कि किसी ने भी टर्नरी ऑपरेटर का उल्लेख नहीं किया है।

var emptyObj = {a:'123', b:'234', c:0};
var defaultValue = 'defaultValue';
var attr = 'someNonExistAttribute';
emptyObj.hasOwnProperty(attr) ? emptyObj[attr] : defaultValue;//=> 'defaultValue'


attr = 'c'; // => 'c'
emptyObj.hasOwnProperty(attr) ? emptyObj[attr] : defaultValue; // => 0

इस तरह, भले ही 'c' का मान 0 हो, फिर भी उसे सही मान मिलेगा।


1
Object.withDefault = (defaultValue,o={}) => {
  return new Proxy(o, {
    get: (o, k) => (k in o) ? o[k] : defaultValue 
  });
}

o = Object.withDefault(42);
o.x  //=> 42

o.x = 10
o.x  //=> 10
o.xx //=> 42

तो ... Proxies का उपयोग करने का मतलब यह भी है कि आप सभी अच्छी वस्तु विधियों पर हार गए हैं :(
— मेरेडिथ

0

यह वास्तव में साथ संभव है Object.create। यह "गैर परिभाषित" गुणों के लिए काम नहीं करेगा। लेकिन उन लोगों के लिए जिन्हें एक डिफ़ॉल्ट मान दिया गया है।

var defaults = {
    a: 'test1',
    b: 'test2'
};

फिर जब आप अपने गुण वस्तु बनाते हैं तो आप उसके साथ करते हैं Object.create

properties = Object.create(defaults);

अब आपके पास दो ऑब्जेक्ट होंगे जहां पहला ऑब्जेक्ट खाली है, लेकिन प्रोटोटाइप defaultsऑब्जेक्ट को इंगित करता है। परीक्षा करना:

console.log('Unchanged', properties);
properties.a = 'updated';
console.log('Updated', properties);
console.log('Defaults', Object.getPrototypeOf(properties));

0

एक दृष्टिकोण यह होगा कि डिफॉल्ट्स ऑब्जेक्ट को लिया जाए और इसे लक्ष्य ऑब्जेक्ट के साथ मर्ज किया जाए। लक्ष्य ऑब्जेक्ट डिफ़ॉल्ट ऑब्जेक्ट में मानों को ओवरराइड करेगा।

jQuery के पास ऐसा .extend()करने की विधि है। हालांकि jQuery की जरूरत नहीं है क्योंकि वेनिला JS कार्यान्वयन हैं जैसे कि यहां पाया जा सकता है:

http://gomakethings.com/vanilla-javascript-version-of-jquery-extend/


-1

मैं यहां एक समाधान की तलाश में आया था क्योंकि हेडर ने मेरी समस्या का वर्णन किया था लेकिन यह वह नहीं है जिसकी मुझे तलाश थी लेकिन मुझे अपनी समस्या का समाधान मिल गया (मैं एक विशेषता के लिए डिफ़ॉल्ट मान रखना चाहता था जो तारीख जैसी गतिशील हो। )।

let Blog = {
title  : String,
image  : String,
body   : String,
created: {type: Date, default: Date.now}
}

उपरोक्त कोड वह समाधान था जिसके लिए मैं अंत में बस गया।

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