कोष्ठक के बिना एक समारोह का आह्वान


275

मुझे आज बताया गया कि बिना कोष्ठक के किसी समारोह को लागू करना संभव है। केवल एक ही तरीका है जिसके बारे में मैं सोच सकता था जैसे applyया फ़ंक्शंस का उपयोग कर रहा था call

f.apply(this);
f.call(this);

लेकिन इन पर कोष्ठकों की आवश्यकता होती है applyऔर callवर्ग एक में हमें छोड़कर। मैंने समारोह को किसी प्रकार के ईवेंट हैंडलर में पास करने के विचार पर भी विचार किया setTimeout:

setTimeout(f, 500);

लेकिन फिर सवाल यह हो जाता है कि "आप setTimeoutबिना कोष्ठक के कैसे आह्वान करते हैं ?"

तो इस पहेली का हल क्या है? आप कोष्ठक का उपयोग किए बिना जावास्क्रिप्ट में एक फ़ंक्शन कैसे लागू कर सकते हैं?


59
अशिष्ट होने की कोशिश नहीं कर रहा हूं, लेकिन मुझे पूछना चाहिए: क्यों?
jehna1

36
@ jehna1 क्योंकि मैं एक सवाल का जवाब दे रहा था कि कार्यों को कैसे लागू किया जाता है और इसे सही किया गया था जब मैंने कहा कि उन्हें अंत में कोष्ठक की आवश्यकता थी।
माइक क्लार्क

3
गजब का! मैंने सोचा नहीं था कि इस सवाल का इतना कर्षण होगा .. शायद मुझे खुद से यह पूछना चाहिए था :-)
अमित

5
इस तरह का सवाल है जो मेरे दिल को तोड़ देता है। इस तरह के दुरुपयोग और शोषण के माध्यम से क्या अच्छा हो सकता है? मैं एक वैध उपयोग के मामले को जानना चाहता हूं, जहां <insert any solution>उद्देश्य से बेहतर या उससे अधिक उपयोगी है f()
धन्यवाद

5
@ ऐरन: आप कहते हैं कि कोई वैध कारण नहीं है, लेकिन, जैसा कि अलेक्जेंडर ओ'मैरा के जवाब बताते हैं, कोई इस सवाल पर विचार कर सकता है कि क्या कोष्ठक को हटाने से कोड निष्पादन को रोकने के लिए पर्याप्त है - या एक ऑबस्पैक्टेड जावास्क्रिप्ट प्रतियोगिता के बारे में क्या? बेशक, यह एक अनुपस्थित उद्देश्य है जब बनाए रखने योग्य कोड लिखने की कोशिश की जा रही है, लेकिन यह एक मनोरंजक quesetion है।
PJTraill

जवाबों:


429

कोष्ठक के बिना एक फ़ंक्शन को कॉल करने के कई अलग-अलग तरीके हैं।

मान लें कि आपके पास यह फ़ंक्शन परिभाषित है:

function greet() {
    console.log('hello');
}

फिर यहां greetबिना कोष्ठकों के कॉल करने के कुछ तरीके दिए गए हैं:

1. कंस्ट्रक्टर के रूप में

साथ newआप कोष्ठकों के बिना एक समारोह आह्वान कर सकते हैं:

new greet; // parentheses are optional in this construct.

से पर MDN newoprator :

वाक्य - विन्यास

new constructor[([arguments])]

2. के रूप में toStringया valueOfकार्यान्वयन

toStringऔर valueOfविशेष विधियाँ हैं: जब रूपांतरण आवश्यक होता है, तो वे अंतर्निहित रूप से कहलाते हैं:

var obj = {
    toString: function() {
         return 'hello';
    }
}

'' + obj; // concatenation forces cast to string and call to toString.

आप इस पैटर्न का उपयोग greetबिना कोष्ठक के कॉल करने के लिए कर सकते हैं :

'' + { toString: greet };

या साथ valueOf:

+{ valueOf: greet };

valueOfऔर toStringवास्तव में @@Primitive विधि (ES6 के बाद से) से बुलाया जाता है , और इसलिए आप उस विधि को भी लागू कर सकते हैं :

+{ [Symbol.toPrimitive]: greet }
"" + { [Symbol.toPrimitive]: greet }

valueOfसमारोह समारोह में 2. बी ओवरराइडिंग

आप प्रोटोटाइपvalueOf पर विधि को ओवरराइड करने के लिए पिछला विचार ले सकते हैं :Function

Function.prototype.valueOf = function() {
    this.call(this);
    // Optional improvement: avoid `NaN` issues when used in expressions.
    return 0; 
};

एक बार जब आप ऐसा कर लेते हैं, तो आप लिख सकते हैं:

+greet;

और यद्यपि वहाँ कोष्ठक रेखा से नीचे हैं, वास्तविक ट्रिगर आमंत्रण में कोई कोष्ठक नहीं हैं। इस बारे में ब्लॉग में देखें "वास्तव में उन्हें बुलाए बिना, जावास्क्रिप्ट में कॉलिंग के तरीके"

3. जनरेटर के रूप में

आप एक जनरेटर फ़ंक्शन (साथ *) को परिभाषित कर सकते हैं , जो एक पुनरावृत्ति देता है । आप इसे प्रसार सिंटैक्स का उपयोग करके या सिंटैक्स के साथ कह सकते हैं for...of

पहले हमें मूल greetफ़ंक्शन के जनरेटर संस्करण की आवश्यकता है :

function* greet_gen() {
    console.log('hello');
}

और फिर हम @@ पुनरावृत्ति विधि को परिभाषित करके कोष्ठक के बिना कहते हैं :

[...{ [Symbol.iterator]: greet_gen }];

आम तौर पर जनरेटर में एक yieldकीवर्ड होता है, लेकिन फ़ंक्शन को कॉल करने के लिए इसकी आवश्यकता नहीं होती है।

अंतिम विवरण समारोह को आमंत्रित करता है, लेकिन यह विनाशकारी भी हो सकता है :

[,] = { [Symbol.iterator]: greet_gen };

या एक for ... ofनिर्माण, लेकिन इसमें स्वयं के कोष्ठक हैं:

for ({} of { [Symbol.iterator]: greet_gen });

ध्यान दें कि आप उपरोक्त मूल कार्य के साथ भी कर सकते हैं greet, लेकिन इसे निष्पादित करने के बाद greet (एफएफ और क्रोम पर परीक्षण किया गया है) एक अपवाद को ट्रिगर करेगा । आप एक try...catchब्लॉक के साथ अपवाद का प्रबंधन कर सकते हैं ।

4. गेट्टर के रूप में

@ jehna1 का इस पर पूरा जवाब है, इसलिए उसे श्रेय दें। यहाँ एक विधि कोष्ठकों को कम करने का एक तरीका है , जो वैश्विक दायरे में कम है , पदावनत__defineGetter__ पद्धति से बचना । इसके Object.definePropertyबजाय उपयोग करता है ।

हमें इसके लिए मूल greetफ़ंक्शन का एक संस्करण बनाने की आवश्यकता है :

Object.defineProperty(window, 'greet_get', { get: greet });

और तब:

greet_get;

windowआपकी वैश्विक वस्तु जो भी है उसे प्रतिस्थापित करें।

आप greetइस तरह से वैश्विक वस्तु पर एक निशान छोड़ने के बिना मूल कार्य कह सकते हैं :

Object.defineProperty({}, 'greet', { get: greet }).greet;

लेकिन कोई यह तर्क दे सकता है कि हमारे यहाँ कोष्ठक हैं (हालाँकि वे वास्तविक आह्वान में शामिल नहीं हैं)।

5. टैग फ़ंक्शन के रूप में

ES6 के बाद से आप इसे इस वाक्य रचना के साथ एक टेम्पलेट शाब्दिक पासिंग फ़ंक्शन कह सकते हैं :

greet``;

"टैग किए गए टेम्पलेट साहित्य" देखें ।

6. प्रॉक्सी हैंडलर के रूप में

ES6 के बाद से, आप एक प्रॉक्सी को परिभाषित कर सकते हैं :

var proxy = new Proxy({}, { get: greet } );

और फिर किसी भी संपत्ति के मूल्य को पढ़ना होगा greet:

proxy._; // even if property not defined, it still triggers greet

इसके कई रूप हैं। एक और उदाहरण:

var proxy = new Proxy({}, { has: greet } );

1 in proxy; // triggers greet

7. उदाहरण चेकर के रूप में

instanceofऑपरेटर को निष्पादित करता है @@hasInstanceजब परिभाषित दूसरे संकार्य, पर विधि:

1 instanceof { [Symbol.hasInstance]: greet } // triggers greet

1
यह एक बहुत ही रोचक तरीका है valueOf
माइक क्लच

4
आप ES6 के बारे में भूल गए:func``;
Ismael Miguel

1
आपने eval :) कॉल करके कोष्ठक का उपयोग किया :)
trincot

1
उस स्थिति में फ़ंक्शन निष्पादित नहीं किया जाता है, लेकिन कॉल करने वाले को पास कर दिया जाता है।
trincot

1
@trincot पाइपलाइन ऑपरेटर के साथ जल्द ही एक और तरीका संभव होगा :'1' |> alert
deniro

224

newऑपरेटर के साथ ऐसा करने का सबसे आसान तरीका :

function f() {
  alert('hello');
}

new f;

जबकि यह अपरंपरागत और अप्राकृतिक है, यह काम करता है और पूरी तरह से कानूनी है।

newऑपरेटर कोष्ठकों की आवश्यकता नहीं है कोई पैरामीटर का उपयोग किया जाता है।


6
सुधार, ऐसा करने का सबसे आसान तरीका एक ऑपरेंड को प्रस्तुत करना है जो फ़ंक्शन अभिव्यक्ति का मूल्यांकन करने के लिए मजबूर करता है। !fपरिणामी फ़ंक्शन के एक उदाहरण को इंस्टेंट किए बिना एक ही चीज़ में परिणाम, (जिसके लिए एक नया संदर्भ बनाने की आवश्यकता होती है)। यह बहुत अधिक प्रभावशाली है और कई लोकप्रिय पुस्तकालयों (जैसे बूटस्ट्रैप) में उपयोग किया जाता है।
TheTheChad

6
@THEtheChad - एक अभिव्यक्ति का मूल्यांकन एक फ़ंक्शन को निष्पादित करने के समान नहीं है, लेकिन अगर आपके पास एक फ़ंक्शन का एक अलग (अच्छे, अधिक आश्चर्य की बात है) आह्वान करने (निष्पादन के कारण) की विधि - एक उत्तर पोस्ट करें!
अमित

एक विस्मयादिबोधक चिह्न, या किसी अन्य एकल वर्ण एकल ऑपरेटर (prepending के बिंदु +, -, ~) इस तरह के पुस्तकालयों में, पुस्तकालय जहां वापसी मान की जरूरत नहीं है की कम से कम संस्करण में एक बाइट को बचाने के लिए है। (अर्थात !function(){}()) सामान्य सेल्फ-कॉलिंग सिंटैक्स है (function(){})()(दुर्भाग्य से सिंटैक्स function(){}()क्रॉस-ब्राउज़र नहीं है) क्योंकि शीर्ष-सबसे सेल्फ-कॉलिंग फ़ंक्शन में आमतौर पर कुछ भी नहीं होता है, यह आमतौर पर इस बाइट की बचत तकनीक का लक्ष्य है
अल्टीमेटर

1
क्या यह सच है? मैंने अभी इसे क्रोम में आज़माया था, और इसे फंक्शन निष्पादन नहीं मिल रहा था। function foo() { alert("Foo!") };उदाहरण के लिए: !fooरिटर्नfalse
ग्लेन 'देवलायस'

95

आप गेटर्स और सेटर का उपयोग कर सकते हैं।

var h = {
  get ello () {
    alert("World");
  }
}

इस स्क्रिप्ट को बस इसके साथ चलाएँ:

h.ello  // Fires up alert "world"

संपादित करें:

हम तर्क भी कर सकते हैं!

var h = {
  set ello (what) {
    alert("Hello " + what);
  }
}

h.ello = "world" // Fires up alert "Hello world"

2 संपादित करें:

आप वैश्विक कार्यों को भी परिभाषित कर सकते हैं जो बिना कोष्ठक के चलाए जा सकते हैं:

window.__defineGetter__("hello", function() { alert("world"); });
hello;  // Fires up alert "world"

और तर्क के साथ:

window.__defineSetter__("hello", function(what) { alert("Hello " + what); });
hello = "world";  // Fires up alert "Hello world"

अस्वीकरण:

जैसा कि @MonkeyZeus ने कहा: कभी भी आप उत्पादन में इस कोड का उपयोग नहीं करेंगे, चाहे आपके इरादे कितने भी अच्छे क्यों न हों।


9
"मैं एक कुल्हाड़ी मारने वाला पागल आदमी हूं, जो आपके कोड को संभालने का सम्मान रखता है, क्योंकि आप बड़ी और बेहतर चीजों की ओर बढ़ चुके हैं, फिर भी मैं आपको जहां रहता हूं वह जानता है।" मैं वास्तव में आशा करता हूं कि यह सामान्य योग्य नहीं है। इसे प्लग-इन के अंदर उपयोग करना जिसमें आप बनाए रखते हैं, स्वीकार्य है। बिजनेस-लॉजिक कोड लिखना, कृपया मेरे कुल्हाड़ी को तेज करते हुए पकड़ लें :)
मंकीज़े

3
@MonkeyZeus हाहा, हाँ! भविष्य के कोडर्स के लिए एक डिस्क्लेमर जोड़ा गया है जो इसे Google से मिल सकता है
jehna1

वास्तव में यह अस्वीकरण बहुत कठोर है। "फ़ंक्शन कॉल के रूप में गेट्टर" के लिए वैध उपयोग के मामले हैं। वास्तव में इसका उपयोग बहुत ही सफल पुस्तकालय में किया जाता है। (क्या आप एक संकेत पसंद करेंगे? :-)
अमित

1
ध्यान दें कि __defineGetter__पदावनत किया जाता है। Object.definePropertyइसके बजाय उपयोग करें ।
फेलिक्स क्लिंग

2
@MonkeyZeus - जैसा कि मैंने स्पष्ट रूप से टिप्पणी में लिखा है - फ़ंक्शन आमंत्रण की इस शैली का उपयोग बड़े पैमाने पर और जानबूझकर किया जा रहा है , एक बहुत ही सफल सार्वजनिक पुस्तकालय में एपीआई के रूप में, आंतरिक रूप से नहीं।
अमित

23

यहाँ एक विशेष स्थिति के लिए एक उदाहरण दिया गया है:

window.onload = funcRef;

यद्यपि वह कथन वास्तव में आह्वान नहीं कर रहा है लेकिन भविष्य के आह्वान को आगे बढ़ाएगा

लेकिन, मुझे लगता है कि इस तरह की पहेलियों के लिए ग्रे-एरिया ठीक हो सकते हैं :)


6
यह अच्छा है, लेकिन यह जावास्क्रिप्ट नहीं है, यह डोम है।
अमित

6
@Amit, DOM ब्राउज़र के JS पर्यावरण का हिस्सा है, जो अभी भी जावास्क्रिप्ट है।
zzzzBov

3
@zzzzBov वेब ब्राउज़र में सभी ECMAScript नहीं चलती है। या आप उन लोगों में से हैं जो "डोम" का इस्तेमाल करते हैं, खासतौर पर ईएसटी को HTML डोम के साथ मिलाने के लिए, जो कि नोड के विपरीत है?
दामियन येरिक

9
@DamianYerrick, मैं DOM को कुछ JS परिवेशों में उपलब्ध एक पुस्तकालय मानता हूँ, जो इसे कुछ वातावरण में उपलब्ध अंडरस्कोर की तुलना में किसी भी जावास्क्रिप्ट को कम नहीं बनाता है। यह अभी भी जावास्क्रिप्ट है, यह सिर्फ एक हिस्सा नहीं है जिसे ECMAScript विनिर्देश में निर्दिष्ट किया गया है।
zzzzBov

3
@zzzzBov, "हालाँकि DOM को अक्सर जावास्क्रिप्ट का उपयोग करके एक्सेस किया जाता है, यह जावास्क्रिप्ट भाषा का हिस्सा नहीं है। इसे अन्य भाषाओं द्वारा भी एक्सेस किया जा सकता है।" । उदाहरण के लिए, फ़ायरफ़ॉक्स डोम कार्यान्वयन के लिए XPIDL और XPCOM का उपयोग करता है। यह इतना स्व-स्पष्ट नहीं है कि आपके निर्दिष्ट कॉलबैक फ़ंक्शन का कॉल जावास्क्रिप्ट में लागू किया गया है। DOM अन्य JavaScript लाइब्रेरी की तरह API नहीं है।
त्रिनकोट

17

यदि हम एक लेटरल थिंकिंग दृष्टिकोण को स्वीकार करते हैं, तो एक ब्राउज़र में कई एपीआई हैं हम किसी भी वास्तविक कोष्ठक के चरित्रों के बिना, एक फ़ंक्शन को कॉल करने सहित जावास्क्रिप्ट को निष्पादित करने के लिए दुरुपयोग कर सकते हैं।

1. locationऔर javascript:प्रोटोकॉल:

इस तरह की एक तकनीक असाइनमेंट javascript:पर प्रोटोकॉल का दुरुपयोग locationकरना है।

काम करने का उदाहरण:

location='javascript:alert\x281\x29'

यद्यपि तकनीकी रूप से \x28 और \x29अभी भी कोष्ठक हैं, एक बार कोड का मूल्यांकन करने के बाद, वास्तविक (और )चरित्र प्रकट नहीं होता है। कोष्ठक जावास्क्रिप्ट के एक तार में बच जाते हैं जिसे असाइनमेंट पर मूल्यांकन किया जाता है।


2 .: onerrorऔरeval

इसी तरह, ब्राउज़र के आधार पर हम वैश्विक का दुरुपयोग कर सकते हैं onerror, इसे सेट करके evalऔर कुछ ऐसा फेंक सकते हैं जो मान्य जावास्क्रिप्ट को कड़ा करेगा। यह एक मुश्किल है, क्योंकि ब्राउज़र इस व्यवहार में असंगत हैं, लेकिन यहां क्रोम के लिए एक उदाहरण है।

क्रोम के लिए काम करने का उदाहरण (फ़ायरफ़ॉक्स नहीं, दूसरों को नहीं):

window.onerror=eval;Uncaught=0;throw';alert\x281\x29';

क्रोम में यह काम करता है क्योंकि पहले तर्क के रूप में throw'test'पास होगा , जो लगभग वैध जावास्क्रिप्ट है। अगर हम इसके बजाय यह पारित करेंगे । अब हमारे पास मान्य जावास्क्रिप्ट है! बस परिभाषित करें , और पेलोड के साथ परीक्षण को बदलें।'Uncaught test'onerrorthrow';test''Uncaught ;test'Uncaught


निष्कर्ष के तौर पर:

ऐसा कोड वास्तव में भयानक है , और इसका उपयोग कभी नहीं किया जाना चाहिए , लेकिन कभी-कभी XSS हमलों में उपयोग किया जाता है, इसलिए कहानी का नैतिक XSS को रोकने के लिए कोष्ठक को छानने पर निर्भर नहीं होता है। ऐसे कोड को रोकने के लिए CSP का उपयोग करना भी एक अच्छा विचार होगा।


यह evalवास्तव में कोष्ठक के पात्रों का उपयोग किए बिना स्ट्रिंग का उपयोग करने और लिखने के समान नहीं है ।
ज़ेव स्पिट्ज

@ZenSpitz हां, लेकिन evalआम तौर पर कोष्ठक की आवश्यकता होती है, इसलिए यह फिल्टर चोरी हैक।
अलेक्जेंडर ओ'मैरा

5
तर्कपूर्ण रूप से \x28और \x29अभी भी कोष्ठक हैं। '\x28' === '('
त्रिनकोट

@trincot मैं जवाब में कवर किया गया बिंदु की तरह है, यह एक पार्श्व सोच दृष्टिकोण है, जिसके लिए एक कारण है जिसमें यह किया जा सकता है दिखाता है। मैंने उत्तर में इसे और स्पष्ट कर दिया है।
अलेक्जेंडर ओ'मैरा

इसके अलावा, जिसने भी इसे हटाने के लिए मतदान किया है, कृपया उत्तर हटाने के लिए दिशानिर्देशों की समीक्षा करें
अलेक्जेंडर ओ'मैरा

1

ES6 में, आपने जो टैग किया हुआ टेम्पलेट लिटरल कहा है ।

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

function foo(val) {
    console.log(val);
}

foo`Tagged Template Literals`;


3
वास्तव में, यह उस उत्तर में है जो मैंने आपसे 1.5 साल पहले पोस्ट किया था ... निश्चित नहीं कि यह एक नया उत्तर देने के योग्य क्यों है?
त्रिनकोट

2
क्योंकि कुछ अन्य लोग, जो अभी एक ही चीज़ को लागू करना चाहते हैं, नए उत्तर का उपयोग कर सकते हैं।
मेहता-रोहन

3
@ मेहता-रोहन, मैं उस टिप्पणी को नहीं समझता। अगर यह समझ में आता है, तो एक ही जवाब पर और अधिक लाभ की नकल क्यों नहीं? मैं नहीं देख सकता कि यह कैसे उपयोगी होगा।
त्रिनकोट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.