2015-05-26 3 views
8

मान लेते हैं कि हम निम्न कार्य हो करते हैं:जावास्क्रिप्ट तर्क स्थानांतरण

var a = function(data, type){ 
 
    var shift = [].shift; 
 
    shift.call(arguments); 
 
    shift.call(arguments); 
 
    shift.call(arguments); 
 
    shift.call(arguments); 
 
    console.log(data); 
 
} 
 

 
a(1,'test', 2, 3);

मैं समझता हूँ कि डेटा और प्रकार सिर्फ बहस में विशिष्ट मूल्यों के लिए संदर्भ। लेकिन अंत में, डेटा 3 के बराबर क्यों है?

+0

उनके बीच का रिश्ता लाइव है ... समाधान एक अलग सरणी का उपयोग करना है जैसे 'var arr = [] .slice.call (तर्क) 'फिर' shift.call (arr) ' –

+0

मुझे कनेक्शन के बारे में पता है:) मैं दिलचस्पी क्यों अंत में यह अपरिभाषित नहीं है, लेकिन 3 – dimko1

+0

क्योंकि जब आप औपचारिक पैरामीटर सूची में सभी मूल्यों की स्थिति शिफ्ट फोन बदल जाता है –

उत्तर

3

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode#Making_eval_and_arguments_simpler से:

सख्त मोड arguments कम बिज़ारेलि जादुई बना देता है।

एक समारोह जिसका पहला तर्क arg है के भीतर सामान्य कोड में, arg की स्थापना भी arguments[0], और इसके विपरीत (जब तक कोई तर्क दिए गए थे या arguments[0] हटा दी जाती है) तय करता है।

arguments सख्त मोड फ़ंक्शंस के लिए ऑब्जेक्ट्स को कार्यान्वित करते समय मूल तर्क संग्रहीत करता है। arguments[i] इसी नामित तर्क का मूल्य ट्रैक नहीं करता है, और न ही किसी नामित तर्क इसी arguments[i] में महत्व को ट्रैक करता है।

आप वास्तव में मुलाकात की "जब तक तर्क [i] हटा दी जाती है" मामले;)

+0

ग्रेट लिंक देखें, यह वास्तविक एक्मास्क्रिप्ट संदर्भ में भी है। मेरा जवाब http://stackoverflow.com/a/30459615/227299 देखें –

2

आपको जो मिलता है वह है [डेटा, प्रकार] और दो और तर्कों का उपयोग नहीं किया जा रहा है। प्रत्येक शिफ्ट से पहले और बाद में एक console.log जोड़ें और आप देखेंगे कि क्या होता है;

var shift = [].shift; 
console.log("args", arguments) 
console.log(data, type); 
// Outputs [1, 'test', 2, 3] => data = 1, type = 'test' 

shift.call(arguments); 
console.log("args", arguments) 
console.log(data, type); 
// Outputs ['test', 2, 3] => data = 'test', type = 2 

shift.call(arguments); 
console.log("args", arguments) 
console.log(data, type); 
// Outputs [2, 3] => data = 2, type = 3 

shift.call(arguments); 
console.log("args", arguments) 
console.log(data, type); 
// Outputs [3] => data = 3, type = 3 (type is keeping it's old value) 

shift.call(arguments); 
console.log("args", arguments) 
console.log(data, type); 
// Outputs [] => data = 3, type = 3 (both are keeping their old value) 

क्या इससे मदद मिलती है?

+0

यह अप्रत्याशित व्यवहार imho –

+0

इसे ऊपर उठाया गया है, लेकिन एक वास्तविक स्पष्टीकरण है ... http://stackoverflow.com/a/30459615/227299 और http://stackoverflow.com/a/30459864/227299 –

0

यहां आपके कोड का एक चरण-दर-चरण है।

var a = function(data, type){ 
    var shift = [].shift;//data points to arguments[0], or 1 
    shift.call(arguments); // arguments[0] is now 'test' 
    shift.call(arguments); // arguments[0] is now 2 
    shift.call(arguments); //arguments[0] is now 3 
    shift.call(arguments); // data pointed @ 3, arguments[0] is undefined 
    console.log(data); 
} 

a(1,'test', 2, 3); 

जे एस पृष्ठभूमि है, जहां अगर arguments की इसी सूचकांक (जो एक सरणी नहीं है) falsy/अपरिभाषित को truthy से चला जाता है में कुछ काम कर रहा प्रतीत हो रहा है, पिछले मान को बनाए रखा जाता है।

0

जो आप देख रहे हैं वह केवल गैर-सख्त जावास्क्रिप्ट के लिए सच है, इसलिए इसे भरोसा नहीं किया जाना चाहिए। http://www.ecma-international.org/ecma-262/5.1/#sec-10.6 देखें, एक ऐसा अनुभाग है जो सख्त और गैर-सख्त मोड के बीच अलग-अलग व्यवहार को समझाता है।

Sp00m ECMAScript विनिर्देश

नोट 1 से एक nice explanation from MDN

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

var a = function(data, type){ 
 
    var shift = [].shift; 
 
    shift.call(arguments); 
 
    shift.call(arguments); 
 
    shift.call(arguments); 
 
    shift.call(arguments); 
 
    console.log(data); 
 
} 
 

 
var b = function(data, type){ 
 
    'use strict'; 
 
    var shift = [].shift; 
 
    shift.call(arguments); 
 
    shift.call(arguments); 
 
    shift.call(arguments); 
 
    shift.call(arguments); 
 
    console.log(data); 
 
} 
 

 
a(1,'test', 2, 3); // 3 
 
b(1,'test', 2, 3); // 1

0

अपने मामले 'डेटा' में तर्क सरणी के पहले की स्थिति के लिए एक संदर्भ है। जब आप अपने फ़ंक्शन को कॉल मूल्यों

arguments[0] => data => 1 
arguments[1] => type => 'test' 
arguments[2] => 2 
arguments[3] => 3 

हैं docs कहते सरणी समारोह बदलाव है कि यह पहला तत्व निकाल देता है। लेकिन यह भी कहते हैं

पारी जानबूझकर सामान्य है; इस विधि को सरणी जैसा ऑब्जेक्ट्स पर बुलाया जा सकता है या लागू किया जा सकता है। वस्तुओं जो लगातार, संख्यात्मक गुण शून्य आधारित की एक श्रृंखला में लंबाई संपत्ति पिछले दर्शाती शामिल नहीं है किसी भी सार्थक तरीके से व्यवहार नहीं कर सकते।

आंतरिक रूप से शिफ्ट फ़ंक्शन डिलीट ऑपरेटर को कॉल करते हैं। चार बार लागू करने के बाद तर्क सरणी [अपरिभाषित, अपरिभाषित] है। अब बात यह है कि है एक चर पर हटाना बुला उसे निकाल देता है, लेकिन अभी भी यदि चर के लिए एक संदर्भ मूल्य नहीं हटाया जाता है

delete arguments[0]; 
delete arguments[1]; 
console.log(arguments); => [2: 2, 3: 3] // Position 0 and 1 were removed. Lenght is still 4 
console.log(data); => 1 
console.log(type); => 'test' 

तो आप देख चर अभी भी परवाह किए बिना संदर्भित आप तर्क से मूल्य नष्ट कर दिया जा रहा है।

संबंधित मुद्दे