क्या करता है "var FOO = FOO || {} ”(जावास्क्रिप्ट या उस चर के लिए एक खाली वस्तु असाइन करें) का मतलब जावास्क्रिप्ट में है?


99

एक ऑनलाइन स्रोत कोड को देखते हुए मैं कई स्रोत फ़ाइलों के शीर्ष पर इस पार आया।

var FOO = FOO || {};
FOO.Bar = …;

लेकिन मुझे नहीं पता कि क्या || {}करता है।

मैं जानता हूं कि {}यह बराबर है new Object()और मुझे लगता है कि ||यह किसी चीज के लिए है जैसे "यदि यह पहले से मौजूद है तो इसके मूल्य का उपयोग करें और नई वस्तु का उपयोग करें।

मैं इसे स्रोत फ़ाइल के शीर्ष पर क्यों देखूंगा?


नोट: यह प्रश्न प्रतिबिंबित करने के लिए संपादित किया गया था कि यह एक कोड पैटर्न है जिसे सामान्यतः जावास्क्रिप्ट स्रोत फ़ाइलों के शीर्ष पर देखा जाता है।
रॉबर्ट हार्वे

जवाबों:


153

के रूप में आपका अनुमान || {}बहुत करीब है।

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

इसका उपयोग करने का कारण यह है कि यदि आपके पास दो (या अधिक) फाइलें हैं:

var MY_NAMESPACE = MY_NAMESPACE || {};
MY_NAMESPACE.func1 = {
}

तथा

var MY_NAMESPACE = MY_NAMESPACE || {};
MY_NAMESPACE.func2 = {
}

दोनों एक ही नामस्थान को साझा करते हैं, तो यह मायने नहीं रखता कि किस क्रम में दो फाइलें भरी हुई हैं, आप अभी भी प्राप्त करते हैं func1और func2सही ढंग से MY_NAMESPACEऑब्जेक्ट के भीतर सही तरीके से परिभाषित होते हैं ।

लोड की गई पहली फ़ाइल प्रारंभिक ऑब्जेक्ट बनाएगीMY_NAMESPACE , और बाद में लोड की गई फ़ाइल ऑब्जेक्ट को बढ़ाएगी

उपयोगी रूप से, यह स्क्रिप्ट के अतुल्यकालिक लोडिंग को भी अनुमति देता है जो समान नामस्थान को साझा करते हैं जो पेज लोडिंग समय में सुधार कर सकते हैं। यदि <script>टैग में deferविशेषता सेट है, तो आप यह नहीं जान सकते कि किस क्रम में उनकी व्याख्या की जाएगी, इसलिए जैसा कि ऊपर वर्णित है, उस समस्या को भी ठीक करता है।


2
यह वास्तव में मामला है, शुरुआत में एक ही घोषणा के साथ कुछ js फाइलें हैं, बहुत बहुत धन्यवाद!
रिकार्डो सांचेज

41
लाइनों के बीच पढ़ने और इसे करने के कारणों को समझाने के लिए +1। यह हमेशा अच्छा होता है जब कोई उत्तर देता है कि उपयोगकर्ता वास्तव में केवल उसी के बजाय चाहता था जो उसने माँगा था। :)
स्पडली

1
मुझे यह कहना पसंद है कि यह # ifndef / # जावास्क्रिप्ट के लिए परिभाषित है :)
डैरेन कोप्प

1
||यह भी वास्तव में उपयोगी है जब आप वैकल्पिक तर्क प्रदान करना चाहते हैं और यदि उपलब्ध नहीं कराया गया है, तो उन्हें डिफ़ॉल्ट रूप से प्रारंभ करें:function foo(arg1, optarg1, optarg2) { optarg1 = optarg1 || 'default value 1'; optarg2 = optart2 || 'defalt value 2';}
पागल २be

1
@ Crazy2be जो डिफ़ॉल्ट रूप से सत्य होने पर काम नहीं करता है, लेकिन गलत मूल्य भी कानूनी हैं, क्योंकि ||ऑपरेटर undefinedसे नहीं बता सकता है falsey
अलनीतक

23
var AEROTWIST = AEROTWIST || {};

मूल रूप से यह रेखा कह रही है कि AEROTWISTचर को चर के मान पर AEROTWISTसेट करें, या इसे किसी खाली वस्तु पर सेट करें।

डबल पाइप ||एक OR स्टेटमेंट है, और OR का दूसरा भाग केवल तभी निष्पादित किया जाता है जब पहला भाग गलत होता है।

इसलिए, यदि AEROTWISTपहले से ही एक मूल्य है, तो इसे उस मूल्य के रूप में रखा जाएगा, लेकिन यदि इसे पहले सेट नहीं किया गया है, तो इसे एक खाली वस्तु के रूप में सेट किया जाएगा।

यह मूल रूप से ऐसा ही कह रहा है:

if(!AEROTWIST) {var AEROTWIST={};}

उम्मीद है की वो मदद करदे।


1
वास्तव में गुंजाइश आपके अंतिम उदाहरण में ठीक होगी क्योंकि JS में ब्लॉक स्कोप नहीं है
Alnitak

@ अलनीतक - मेह, आप सही कह रहे हैं; मैं हाल ही में बंद करने के साथ काम कर रहा हूं और मैं मूल बातें भूल गया हूं। मैं उत्तर संपादित करूँगा।
स्पडली

6

के लिए एक और आम उपयोग || एक अपरिभाषित फ़ंक्शन पैरामीटर के लिए एक डिफ़ॉल्ट मान भी सेट करना है:

function display(a) {
  a = a || 'default'; // here we set the default value of a to be 'default'
  console.log(a);
}

// we call display without providing a parameter
display(); // this will log 'default'
display('test'); // this will log 'test' to the console

आमतौर पर अन्य प्रोग्रामिंग में बराबर है:

function display(a = 'default') {
  // ...
}

आपको फ़ंक्शन के varसामने की आवश्यकता नहीं है a, aएक औपचारिक पैरामीटर के रूप में फ़ंक्शन के निष्पादन संदर्भ में प्रवेश करता है , इसलिए यह पहले से ही घोषित है।
फेब्रीसो मैटे

6

var FOO = FOO || {};कवर करने वाले दो मुख्य भाग हैं।

# 1 ओवरराइडिंग को रोकना

कल्पना करें कि आपके पास कई फाइलों पर आपका कोड विभाजित है और आपके सहकर्मी भी नामक ऑब्जेक्ट पर काम कर रहे हैं FOO। तब यह इस मामले को जन्म दे सकता है कि किसी ने पहले से ही FOOइसे परिभाषित किया है और इसे (एक skateboardफ़ंक्शन की तरह ) कार्यक्षमता प्रदान की है। तब आप इसे ओवरराइड करेंगे, यदि आप जाँच नहीं कर रहे थे कि क्या यह पहले से मौजूद है।

समस्यात्मक मामला:

// Definition of co-worker "Bart" in "bart.js"
var FOO = {};

FOO.skateboard = function() {
  alert('I like skateboarding!');
};

// Definition of co-worker "Homer" in "homer.js"
var FOO = {};

FOO.donut = function() {
  alert('I like donuts!');
};

skateboardयदि आप अपने HTML में जावास्क्रिप्ट फ़ाइल homer.jsको लोड करते हैं तो इस स्थिति में फ़ंक्शन चला जाएगा bart.jsक्योंकि होमर एक नई FOOवस्तु को परिभाषित करता है (और इस प्रकार बार्ट से मौजूदा को ओवरराइड करता है) इसलिए यह केवल donutफ़ंक्शन के बारे में जानता है ।

इसलिए आपको var FOO = FOO || {};इसका उपयोग करने की आवश्यकता है जिसका अर्थ है "FOO को FOO को सौंपा जाएगा (यदि यह पहले से मौजूद है) या एक नई रिक्त वस्तु (यदि FOO पहले से मौजूद नहीं है)।

उपाय:

var FOO = FOO || {};

// Definition of co-worker Bart in bart.js
FOO.skateboard = function() {
  alert('I like skateboarding!');
};

// Definition of co-worker Homer in homer.js
var FOO = FOO || {};

FOO.donut = function() {
  alert('I like donuts!');
};

क्योंकि बार्ट और होमर अब FOOअपने तरीकों को परिभाषित करने से पहले अपने अस्तित्व की जाँच कर रहे हैं , आप एक-दूसरे के तरीकों (यदि उनके अलग-अलग नाम हैं) को ओवरराइड किए बिना लोड कर सकते हैं bart.jsऔर कर सकते हैं homer.js। तो आपको हमेशा एक FOOवस्तु मिलेगी जिसमें विधियाँ हैं skateboardऔर donut(याय!)।

# 2 एक नई वस्तु को परिभाषित करना

यदि आपने पहले उदाहरण के माध्यम से पढ़ा है तो आप पहले से ही अब इसका उद्देश्य क्या है || {}

क्योंकि यदि कोई विद्यमान FOOवस्तु नहीं है, तो OR-case सक्रिय हो जाएगा और एक नई वस्तु बनाता है, इसलिए आप इसे कार्य सौंप सकते हैं। पसंद:

var FOO = {};

FOO.skateboard = function() {
  alert('I like skateboarding!');
};

3

यदि AEROTWIST में कोई मान नहीं है या यह शून्य है या अपरिभाषित है तो AEROTWIST को दिया गया मान {} (एक रिक्त वस्तु) होगा


1

||ऑपरेटर दो मानों लेता है:

a || b

यदि सत्य है , तो यह वापस आ जाएगा a। नहीं तो वापस लौट आएगा b

Falsy मान हैं null, undefined, 0, "", NaNऔर false। सत्य मूल्य बाकी सब कुछ हैं।

तो अगर aसेट नहीं किया गया है (यह है undefined) यह वापस आ जाएगा b


मुझे यकीन है कि नहीं कर रहा हूँ truthy और falsey वास्तविक शब्द के रूप में perpetuated किया जाना चाहिए। मनोरंजक, लेकिन बिल्कुल मानक नहीं। :-)
परिक्रमा करें

4
@Orbling वे आमतौर पर JS में ऐसे मूल्यों के बारे में बात करने के लिए उपयोग किए जाते हैं।
अलनीतक

एक ऑपरेटर को सही ढंग से वर्णन करने के लिए +1, क्योंकि यह तार्किक ऑपरेटर नहीं है। कभी-कभी इसे "डिफ़ॉल्ट ऑपरेटर" कहा जाता है।
टिम बुथ

@ टिम ||जेएस (और पर्ल) और सी, सी ++ और जावा में संस्करण के बीच एकमात्र अंतर यह है कि जेएस परिणाम को बूलियन के रूप में नहीं रखता है। यह अभी भी एक तार्किक ऑपरेटर है।
अलनीतक

@Alnitak: अतीत में JS डेवलपर्स की गैर-पेशेवर पृष्ठभूमि के कारण संभवतः।
परिक्रमा

-1

ध्यान दें कि IE के कुछ संस्करण में यह कोड अपेक्षित रूप से काम नहीं करेगा। क्योंकि var, चर को फिर से परिभाषित और नियत किया गया है - यदि मुझे समस्या को सही ढंग से याद है - तो आप हमेशा एक नई वस्तु रखेंगे। इस समस्या को हल करना चाहिए:

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