2015-10-25 7 views
11

हर बार जब मैं कुछ वर्ग बनाने के लिए, मैं एक ही उबाऊ प्रक्रिया क्या करने की जरूरत:ECMAScript में एक छोटा वर्ग initialisation 6

class Something { 
    constructor(param1, param2, param3, ...) { 
    this.param1 = param1; 
    this.param2 = param2; 
    this.param3 = param3; 
    ... 
    } 
} 

वहाँ इसे और अधिक सुंदर और कम करने के लिए कोई तरीका है? मैं बेबेल का उपयोग करता हूं, इसलिए कुछ ES7 प्रयोगात्मक सुविधाओं की अनुमति है। शायद सजावटी मदद कर सकते हैं?

+2

क्या इसे कक्षा होने की आवश्यकता है? आप शॉर्टैंड ऑब्जेक्ट का उपयोग कर सकते हैं ताकि परम को उनके नाम दोहराए बिना गुणों के रूप में असाइन किया जा सके। – Touffy

+1

अपने अंतिम प्रश्न का उत्तर देने के लिए, सजावटी यहां सहायता नहीं करेंगे क्योंकि उन्हें 'क्लास कन्स्ट्रक्टर' – CodingIntrigue

उत्तर

10

आप Object.assign उपयोग कर सकते हैं:

class Something { 
    constructor(param1, param2, param3) { 
    Object.assign(this, {param1, param2, param3}); 
    } 
} 

यह एक ES2015 (उर्फ ES6) विशेषता यह है कि एक लक्ष्य वस्तु को खुद गणनीय एक या अधिक स्रोत वस्तुओं के गुण प्रदान करती है।

माना जाता है कि आपको दो बार तर्क नाम लिखना है, लेकिन कम से कम यह बहुत छोटा है, और यदि आप इसे अपने मुहावरे के रूप में स्थापित करते हैं, तो यह आपके लिए अच्छा होता है जब आपके पास तर्क है जो आप चाहते हैं और अन्य जो आप करते हैं 'टी, जैसे:

class Something { 
    constructor(param1, param2, param3) { 
    Object.assign(this, {param1, param3}); 
    // ...do something with param2, since we're not keeping it as a property... 
    } 
} 

उदाहरण: (live copy on Babel's REPL):

class Something { 
    constructor(param1, param2, param3) { 
    Object.assign(this, {param1, param2, param3}); 
    } 
} 
let s = new Something('a', 'b', 'c'); 
console.log(s.param1); 
console.log(s.param2); 
console.log(s.param3); 

आउटपुट:

 
a 
b 
c 
+0

से जोड़ा नहीं जा सकता है, यह बहुत साफ है, लेकिन आप अभी भी पैरा नामों को दोहरा रहे हैं (एक बार तर्क सूची में, एक बार असाइन कॉल में)। आप 'तर्क' क्लोन कर सकते हैं, पूर्वनिर्धारित गुणों को हटा सकते हैं, और इसे 'असाइन' करने के लिए पास कर सकते हैं। – Touffy

+0

@ टॉफी: क्या तर्कों के लिए 'तर्क * नाम * गुण हैं? मेरा मतलब है, '0',' 1', और '2' के अलावा अन्य नामों के साथ? अगर ऐसा है तो यह मेरे लिए नया है। –

+0

हमम सही नहीं है। मुझे लगता है कि आप उन्हें फ़ंक्शन के टूस्ट्रिंग से आसानी से पार्स कर सकते हैं, लेकिन यह बदसूरत हो रहा है। – Touffy

3

दुर्भाग्यवश, आप जो कुछ भी कर सकते हैं वह Object.assign जैसी साधारण चीजें हैं, लेकिन यदि आप दो बार सभी पैराम टाइप करने की रिडंडेंसी को हटाने की कोशिश कर रहे हैं (एक बार कन्स्ट्रक्टर हस्ताक्षर में और एक बार असाइनमेंट में) तो आप ऐसा नहीं कर सकते हैं।

उसने कहा, आप इस तरह एक हैक कर सकते हैं। हालांकि मुझे यकीन नहीं है कि इसके साथ आने वाले obfuscation के प्रयास और modicum इसके लायक है।

var dependencies = ['param1', 'param2', 'param3']; 

class Something { 
    constructor(...params) { 
    params.forEach((param, index) => this[dependencies[index]] = param); 
    } 
} 

var something = new Something('foo', 'bar', 'baz'); 
// something.param1 === 'foo' 

इस तरह आप तर्क के नाम की एक सारिणी का प्रयोग कर रहे हैं, तो एक संदर्भ के रूप में है कि एक ही सरणी का उपयोग करते समय Something के अपने उदाहरण पर गुण का निर्माण। यह पैटर्न एक कोणीय अनुप्रयोग में अच्छी तरह से काम करेगा जहां आप $inject संपत्ति सेट करके खनन के माध्यम से निर्भरता नामों को संरक्षित करने का प्रयास कर रहे हैं।

Something.$inject = dependencies; 

पुनश्च - शास्त्रीय भाषाओं के अनावश्यक नरक है कि मैं सोचा मैं जब मैं एक जे एस डेवलपर बन गया से भाग गया में आपका स्वागत है: ईमानदारी से पी

, तो आप शायद सिर्फ एक क्लासिक वस्तु जब तक शाब्दिक का उपयोग करना चाहिए आपको वास्तव में वास्तविक वर्ग की औपचारिकता की आवश्यकता है।

संपादित करें: मुझे लगता है कि यदि आप एक शाब्दिक और वास्तविक वर्ग की औपचारिकता की आसानी चाहते हैं तो आप अपने कन्स्ट्रक्टर में एक वस्तु को शाब्दिक स्वीकार कर सकते हैं।

class Something { 
    constructor(params) { 
    Object.keys(params).forEach((name) => this[name] = params[name]); 
    } 
} 

var something = new Something({ 
    param1: 'foo', 
    param2: 'bar', 
    param3: 'baz' 
}); 

लेकिन अब तुम सिर्फ एक गतिशील वर्ग है कि किसी भी गुणों के साथ instantiated जा सकती है, में एक वर्ग बदल दिया है, एक वस्तु शाब्दिक की तरह थोड़े: पी

आमतौर पर मैं एक वर्ग चाहता हूँ क्योंकि मैं औपचारिक रूप देने चाहते हैं ऑब्जेक्ट और एक सतत और सख्ती से परीक्षण योग्य एपीआई प्रस्तुत करते हैं।

+1

यह बदसूरत है, लेकिन आपको फ़ंक्शन के तर्कों के नाम देगा ताकि आप उन्हें बाहरी सरणी के बजाय फ़ंक्शन परिभाषा में लिख सकें: 'arguments.callee.toString()। मिलान (/^function। *? \ ((। *?) \) /) [1] .split (/, \ s * /)} ' – Touffy

+1

@ टॉफी जो मेरे लिए काम नहीं करेगा। सख्त मोड मुझे 'arguments.callee' तक पहुंचने की अनुमति नहीं देगा, इसलिए आपको एक [आगे कामकाज] की आवश्यकता हो सकती है (http://stackoverflow.com/questions/29572466/how-do-you-find-out-the-caller- फ़ंक्शन-इन-जावास्क्रिप्ट-जब-उपयोग-सख्त-सक्षम-सक्षम) उस समाधान के लिए, इसे और भी बदसूरत बनाते हैं। – CodingIntrigue

1

हम प्रत्येक कक्षा के भीतर एक स्थिर विधि बना सकते हैं जो arguments ऑब्जेक्ट और नामों की एक सरणी लेता है और Object.assign का उपयोग करके नए उदाहरण को असाइन किया जा सकता है।

Babel REPL का उपयोग करके इसे देखें।

class Something { 
    static buildArgs (ctx, args, paramNames) { 
    let obj = {} 
    Array.from(args).forEach(function (arg, i) { 
     let name = paramNames[i] || i 
     obj[name] = args[i] 
    }) 
    Object.assign(ctx, obj) 
    } 

    constructor() { 
    Something.buildArgs(this, arguments, [ 
     'param1', 
     'param2' 
    ]); 
    console.log(this) 
    } 
} 

new Something('one', 'two') 

बेशक एक विधि buildArgs के अलावा इसका मतलब है कि इस समाधान में कम नहीं है, लेकिन constructor का मुख्य भाग है और हम भी इन फायदे हैं:

  1. आप केवल पैरामीटर नाम एक बार लिख रहे हैं ।
  2. आप खनन के खिलाफ सुरक्षित हैं।

कोड ऊपर रह सकते हैं अतिरिक्त तर्कों (i >= paramNames.length) लेकिन यदि यह व्यवहार अवांछनीय है ऐसा है कि ये अभी भी पार्स हैं, लेकिन उदाहरण के लिए निर्दिष्ट नहीं हम इसे संशोधित कर सकते हैं:

class Something { 
    static buildArgs (ctx, args, paramNames) { 
    let obj = {instance: {}, extra: {}} 
    Array.from(args).forEach(function (arg, i) { 
     let name = paramNames[i] || i 
     if (name) { 
      obj.instance[name] = args[i] 
     } else { 
      obj.extra[i] = args[i] 
     } 
    }) 
    Object.assign(ctx, obj) 
    } 

    constructor() { 
    let args = Something.buildArgs(this, arguments, ['param1', 'param2']); 
    // Do stuff with `args.extra` 
    } 
} 

या पूरी तरह नजरअंदाज कर दिया:

static buildArgs (args, paramNames) { 
    let obj = {} 
    Array.from(args).forEach(function (arg, i) { 
     let name = paramNames[i] 
     if (name) obj[name] = args[i] 
    }) 
    return obj 
    } 
संबंधित मुद्दे