क्यों {} + {} NaN केवल क्लाइंट की तरफ है? Node.js में क्यों नहीं?


136

जबकि [] + []एक खाली स्ट्रिंग है, [] + {}है "[object Object]", और {} + []है 0{} + {}NaN क्यों है ?

> {} + {}
  NaN

क्यों मेरे सवाल नहीं है ({} + {}).toString()है "[object Object][object Object]", जबकि NaN.toString()है "NaN", इस भाग का उत्तर यहाँ पहले से ही है

मेरा सवाल यह है कि ऐसा केवल क्लाइंट की तरफ से क्यों होता है? सर्वर की तरफ ( Node.js ) {} + {}है "[object Object][object Object]"

> {} + {}
'[object Object][object Object]'

संक्षेप :

ग्राहक पक्ष पर:

 [] + []              // Returns ""
 [] + {}              // Returns "[object Object]"
 {} + []              // Returns 0
 {} + {}              // Returns NaN

 NaN.toString()       // Returns "NaN"
 ({} + {}).toString() // Returns "[object Object][object Object]"
 var a = {} + {};     // 'a' will be "[object Object][object Object]"

Node.js में:

 [] + []   // Returns "" (like on the client)
 [] + {}   // Returns "[object Object]" (like on the client)
 {} + []   // Returns "[object Object]" (not like on the client)
 {} + {}   // Returns "[object Object][object Object]" (not like on the client)

4
यह सिर्फ ब्राउज़र कंसोल है जो ऐसा करता है। कंसोल पर लॉग इन करने का प्रयास करें और यह NodeJS की तरह ही है। jsbin.com/oveyuj/1/edit
elclanrs

2
वास्तव में डुप्लिकेट नहीं, मैं NodeJS जवाब के लिए पूछ रहा हूं। दोबारा
खुलने के

4
हम्म ... सॉरी। हालाँकि, stackoverflow.com/questions/9032856/… अभी भी प्रासंगिक है और पहले हाफ का जवाब देता है
John Dvorak

3
मत भूलो कि {}एक अभिव्यक्ति के रूप में या संदर्भ के आधार पर एक वस्तु आदिम के रूप में व्याख्या की जा सकती है। हो सकता है कि कोड क्लाइंट और सर्वर पर समान हो लेकिन {}कोड दर्ज करने के अलग-अलग संदर्भों के कारण यह अलग-अलग व्याख्या कर रहा है।
पलाशू

18
कृपया पुनः खोलें और फिर इस प्रश्न को बार-बार बंद करना बंद करें क्योंकि यह प्रश्न वास्तव में डुप्लिकेट नहीं है
एल्विन वोंग

जवाबों:


132

अपडेटेड नोट: यह क्रोम 49 में तय किया गया है

बहुत दिलचस्प सवाल! में खुदाई करते हैं।

मुख्य कारण

अंतर की जड़ यह है कि Node.js इन कथनों का मूल्यांकन कैसे करता है बनाम क्रोम विकास उपकरण कैसे करते हैं।

Node.js क्या करता है

Node.js का उपयोग करता repl इस के लिए मॉड्यूल।

Node.js REPL स्रोत कोड से :

self.eval(
    '(' + evalCmd + ')',
    self.context,
    'repl',
    function (e, ret) {
        if (e && !isSyntaxError(e))
            return finish(e);
        if (typeof ret === 'function' && /^[\r\n\s]*function/.test(evalCmd) || e) {
            // Now as statement without parens.
            self.eval(evalCmd, self.context, 'repl', finish);
        }
        else {
            finish(null, ret);
        }
    }
);

यह ({}+{})क्रोम डेवलपर टूल में चलने की तरह ही काम करता है , जो "[object Object][object Object]"आपकी अपेक्षा के अनुरूप भी होता है।

क्रोम डेवलपर टूल क्या करते हैं

दूसरी ओर क्रोम डवलपर टूल निम्नलिखित कार्य करता है :

try {
    if (injectCommandLineAPI && inspectedWindow.console) {
        inspectedWindow.console._commandLineAPI = new CommandLineAPI(this._commandLineAPIImpl, isEvalOnCallFrame ? object : null);
        expression = "with ((window && window.console && window.console._commandLineAPI) || {}) {\n" + expression + "\n}";
    }
    var result = evalFunction.call(object, expression);
    if (objectGroup === "console")
        this._lastResult = result;
    return result;
}
finally {
    if (injectCommandLineAPI && inspectedWindow.console)
        delete inspectedWindow.console._commandLineAPI;
}

तो मूल रूप से, यह callअभिव्यक्ति के साथ ऑब्जेक्ट पर प्रदर्शन करता है । अभिव्यक्ति की जा रही है:

with ((window && window.console && window.console._commandLineAPI) || {}) {
    {}+{};// <-- This is your code
}

तो, जैसा कि आप देख सकते हैं, रैपिंग कोष्ठक के बिना, अभिव्यक्ति को सीधे विकसित किया जा रहा है।

क्यों Node.js अलग तरह से कार्य करता है

Node.js का स्रोत इसे सही ठहराता है:

// This catches '{a : 1}' properly.

नोड ने हमेशा इस तरह का अभिनय नहीं किया। यहां वास्तविक प्रतिबद्धता है जिसने इसे बदल दिया है । रयान ने इस बदलाव पर निम्नलिखित टिप्पणी छोड़ी: "अंतर के उदाहरण के साथ सुधार करें कि कैसे REPL कमांडों को विकसित किया गया है"।


राइनो

अद्यतन - ओपी इस बात में रुचि रखता था कि राइनो कैसे व्यवहार करता है (और यह क्रोम डेत्टुल्स और नोड्ज के विपरीत क्यों व्यवहार करता है)।

राइनो क्रोम डेवलपर टूल्स और Node.js की REPL के विपरीत एक पूरी तरह से अलग JS इंजन का उपयोग करता है जो दोनों V8 का उपयोग करते हैं।

जब आप राइनो शेल में राइनो के साथ एक जावास्क्रिप्ट कमांड को विकसित करते हैं तो यहां की मूल पाइप लाइन होती है।

  • खोल चलता है org.mozilla.javascript.tools.shell.main

  • बारी में, यह कहता है इस new IProxy(IProxy.EVAL_INLINE_SCRIPT); उदाहरण के लिए, यदि कोड इनलाइन स्विच -e के साथ सीधे पारित किया गया था।

  • यह IProxy की runविधि को हिट करता है ।

  • यह आह्वान करता है evalInlineScript( src )। यह बस स्ट्रिंग संकलित करता है और इसे विकसित करता है।

मूल रूप से:

Script script = cx.compileString(scriptText, "<command>", 1, null);
if (script != null) {
    script.exec(cx, getShellScope()); // <- just an eval
}

तीन में से, राइनो का खोल वह है जो evalकिसी भी लपेट के बिना एक वास्तविक के सबसे करीब काम करता है । राइनो एक वास्तविक eval()बयान के सबसे करीब है और आप evalउससे वैसा ही व्यवहार करने की उम्मीद कर सकते हैं ।


1
(वास्तव में जवाब का एक हिस्सा नहीं है, लेकिन उल्लेख करने योग्य नोड्ज आरईपीएल का उपयोग करते समय डिफ़ॉल्ट रूप से ईगलिंग के लिए वीएम मॉड्यूल का उपयोग करता है, और सिर्फ एक जावास्क्रिप्ट नहीं है eval)
बेंजामिन ग्रुएनबाम

क्या आप समझा सकते हैं कि राइनो , उदाहरण के लिए, टर्मिनल (क्रोम क्रोम ही नहीं) में भी यही काम करता है?
Ionică Bizău

5
+10 अगर यह संभव था! वाह यार, ... तुम सच में जीवन नहीं है या तुम सच में होशियार हो मुझसे ऐसा कुछ जानने के लिए। कृपया, मुझे बताएं कि आपने इस उत्तर को खोजने के लिए थोड़ी खोज की :) :)
शमूएल

7
@ शमूएल यह सब ले लिया स्रोत पढ़ रहा है - मैं कसम खाता हूँ! क्रोम में, यदि आप 'डीबगर' दर्ज करते हैं। , आप पूरे पाइप को प्राप्त करते हैं - यह आपको सीधे 'के साथ' को केवल एक फ़ंक्शन के ऊपर फेंक देगा evaluateOn। नोड में, सब कुछ बहुत अच्छी तरह से प्रलेखित है - उनके पास सभी इतिहासों के साथ एक समर्पित REPL मॉड्यूल है, जो गिट पर अच्छा और आरामदायक है, अपने खुद के कार्यक्रमों से पहले REPLs का उपयोग करते हुए, मुझे पता था कि मुझे कहाँ देखना है :) मुझे खुशी है कि आपने इसे पसंद किया और पाया यह मददगार है, लेकिन मैं अपनी बुद्धि के बजाय इन कोड आधारों (देव-उपकरण और नोडज) के साथ अपनी परिचितता के लिए इसका एहसानमंद हूं। स्रोत पर सीधे जाना अक्सर सबसे आसान होता है।
बेंजामिन ग्रुएनबाम

अपडेट - क्रोम में कंसोल एपीआई को थोड़ा अपडेट किया गया है, जबकि यहां सामान्य विचार सही है, पोस्ट किया गया कोड क्रोम के सबसे हाल के संस्करण के लिए सटीक नहीं है। देखें chromium.googlesource.com/chromium/blink.git/+/master/Source/...
बेंजामिन Gruenbaum
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.