2017-05-21 13 views
5

इंटरसेप्टिंग मैं a[i] जैसे प्रत्येक सरणी एक्सेसर के साथ कुछ साइड इफेक्ट को जोड़ना चाहता हूं। उदाहरण के लिए, पक्ष प्रभाव कंसोल के लिए एक संदेश लिख रहे हैं, निम्नलिखित कार्यक्रम:जावास्क्रिप्ट सरणी एक्सेसर

1 // access a[0] 
 
2 // access a[1] 
 
3 // access a[2] 
 
6 // print original total

मामले में:

var array = [1, 2, 3] 
 
var total = 0; 
 
for (var i in array) { 
 
    total += array[i] 
 
} 
 
console.log(total);
तरह उत्पादन लौटना चाहिए मुझे एक सरणी विधि push को अवरुद्ध करने में दिलचस्पी थी, मैं इस ब्लॉग post और तकनीक से तकनीक का उपयोग करूंगा एड एक इंटरसेप्टर:

var _push = Array.prototype.push; 
 
Array.prototype.push = function(item) { 
 
    console.log('pushing ', item, ' into ', this); 
 
    _push.apply(this, arguments); 
 
}

यह संभव एक सरणी एक्सेसर के लिए एक ही चाल लागू है? या इस समस्या के लिए एक बेहतर समाधान क्या होगा? एक महत्वपूर्ण नोट यह है कि मैं प्रोग्राम के मूल कोड को संशोधित नहीं करना चाहता हूं। इसलिए, जेएस proxies का उपयोग करने के लिए गेटर्स और सेटर्स को अवरुद्ध करने के लिए मेरी समस्या के लिए एक वैध विकल्प नहीं लगता है।

एक विशेष साइड इफेक्ट, मैं परिचय देना चाहता हूं, यदि एक्सेस किए गए मान को अपरिभाषित किया गया है (जेएस एरे के लिए सीमा अपवाद से बाहर सूचकांक में कुछ बदलाव) में अपवाद बढ़ाना है। मैं जांचता हूं कि वर्तमान में एक्सेसिंग मान बराबर है या नहीं undefined, और उस मामले में अपवाद फेंक दें, अन्यथा केवल मूल मान वापस करें।

+2

[एक में बदलावों का पता लगाना की संभावित डुप्लिकेट प्रॉक्सी ऑब्जेक्ट का उपयोग कर जावास्क्रिप्ट सरणी] (http://stackoverflow.com/questions/35610242/detecting-changes-in-a-javascript-array-using-the-proxy-object) –

+0

@ मोहम्मद जो लिंक किया गया प्रश्न मदद नहीं करता है जीई overriding के साथ ओपी हालांकि अंतर्निर्मित सरणी के तंत्रिका व्यवहार। –

+0

मैं @le_m –

उत्तर

3

आप Arrays के उस एक्सेसर को ओवरराइड नहीं कर सकते हैं। यहाँ एक उदाहरण:

Object.defineProperty(Array.prototype, 0, { 
 
    get: function() { return "my get on 0"; } 
 
}); 
 
var a = [1,2,3]; 
 
console.log(a[0]); // output: 1

लेकिन यदि आप एक संपत्ति के साथ एक ही है जो वास्तव में सरणी में मौजूद नहीं है करने की कोशिश, तो आप इसे प्राप्त करेंगे:

Object.defineProperty(Array.prototype, 5, { 
 
    get: function() { return "my get on 5"; } 
 
}); 
 
var a = [1,2,3]; 
 
console.log(a[5]); // output: my get on 5

आप क्या कर सकते हैं एक छोटा सा कामकाज एक्सेसिंग है Arrays के get विधि के माध्यम से तत्व।

Array.prototype.get = function(i) { 
 
    console.log('my print'); 
 
    console.log(this[i]); 
 
    return "this is!"; 
 
}; 
 
var a = [1,2,3]; 
 
console.log(a.get(0)); // output: my print 1 this is!

तो, वापस अपने प्रश्न के लिए आ रहा है कि आप कुछ कर सकता है जैसे आप push के लिए लेकिन get साथ, से परहेज प्रॉक्सी किया:

Array.prototype.get = function (i) { 
 
    console.log('Accessing element: ' + this[i]); 
 
    console.log(this); 
 
    return this[i]; 
 
}; 
 
var array = [1, 2, 3]; 
 
var total = 0; 
 
// be careful that now you cannot do anymore 
 
// for (var i in array), because inside the array there is also the property get defined and it will cycle also on that 
 
// if you want to cycle again in that way, you need the check through hasOwnProperty method 
 
/* 
 
for(var i in array) { 
 
    if (array.hasOwnProperty(i)){ 
 
    console.log(i); 
 
    total += array.get(i); 
 
    } 
 
} 
 
*/ 
 
for(var i = 0; i < array.length; i++) { 
 
    total += array.get(i); 
 
} 
 
console.log(total);

सिर्फ जवाब पूरा करने के लिए, क्या आपको बस इतना करना सरणी के reduce विधि के साथ एक पंक्ति में किया जा सकता है की कोशिश कर रहे:

var array = [1, 2, 3]; 
 
var result = array.reduce(function (accumulator, actual) { 
 
    return accumulator + actual; 
 
}, 0); 
 
console.log(result);

मैं दृढ़ता से इन accessors का ओवरराइड से बचने के लिए आप सलाह देते हैं। आप कोड का आधार बदल देंगे, इसलिए तीसरे पक्ष के लोगों को यह समझना असंभव होगा कि सभी कोड पढ़ने के बिना क्या हो रहा है। इसके अलावा आप बहुत सारी अंतर्निहित उपयोगी विधियों को खो देंगे। मुझे आशा है कि यह

पेजों में सहायता करता है। आपके संपादन के बाद, अपरिभाषित मानों की जांच करने और अपवादों को बढ़ाने के लिए आप प्राप्त विधि के ओवरराइड के अंदर चेक जोड़ सकते हैं। लेकिन मेरा सुझाव सिर्फ सरणी को फ़िल्टर करने, अपरिभाषित मानों का पता लगाने और उनसे छुटकारा पाने के लिए है। ध्यान दें कि मैं डबल बराबर का उपयोग कर रहा हूं। क्योंकि undefined == null लेकिन undefined !== null। इस तरह आप अपरिभाषित और शून्य मान दोनों को हटा देंगे। यदि आप केवल अपरिभाषित को हटाना चाहते हैं, तो इसे if (typeof element === 'undefined') पर बदलें।

तो कुछ इस तरह, सरणियों के साथ filter विधि सिर्फ एक पाश का उपयोग कर:

var data = [1, 2, undefined, 3, 4, undefined, 5]; 
 

 
data = data.filter(function(element, index) { 
 
    // note that I am using the double equal. because undefined == null but undefined !== null. 
 
    // in this way you will remove both undefined and null values 
 
    // if you want to remove only undefined, change it to if (typeof element === 'undefined') 
 
    if (element == null) { 
 
    console.log('found and undefined null value at index: ' + index); 
 
    } 
 
    return element != null; 
 
}); 
 
console.log(data); // array without undefined and null values

+0

उत्तर के लिए धन्यवाद। यदि मैं जो हासिल करना चाहता हूं वह संभव नहीं है, तो मुझे आपके द्वारा सुझाए गए 'get' विधि' के विकल्प पर वापस आना होगा। मैंने इस सवाल को थोड़ा सा अद्यतन भी किया, जिस तरह से अपवाद की मुझे सबसे ज्यादा पसंद है। –

+0

आप यह सुनिश्चित करने के लिए गेट विधि बदल सकते हैं कि यह अपवाद पहले अपरिभाषित है या नहीं, लेकिन मेरा सुझाव इस मामले में एक और है। मैं इसे उत्तर में जोड़ूंगा, टिप्पणियों की तुलना में कोड लिखना आसान है – quirimmo

+0

ने इसे अपने विशिष्ट मामले – quirimmo

2

यह कोड को संशोधित करने के बिना संभव नहीं है:

  • आप कर सकते हैं सरणी शाब्दिक कन्स्ट्रक्टर ओवरराइड टी। Overwriting the Array constructor does not affect [], right?

  • आप लूप में उपयोग किए गए इटरेटर के व्यवहार को ओवरराइड भी नहीं कर सकते हैं। https://tc39.github.io/ecma262/#sec-enumerate-object-properties

  • देखें आप Array.prototype पर गेटर कार्यों में अवरोध उत्पन्न कर के साथ गुण जोड़ सकते हैं, वहीं उन प्रोटोटाइप गुण पहुँचा नहीं किया जाएगा जब एक ही नाम के गुण सरणी उदाहरण पर मौजूद हैं के रूप में अपने उदाहरण में मामला है।

तो आपको कोड को संशोधित करने, कोड को पूर्ववत करने या कोड चलाने वाले जावास्क्रिप्ट इंजन को संशोधित करने की आवश्यकता है।

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

// Override default array constructor: 
 
Array = (function(Array) { 
 
    function LoggingArray(...args) { 
 
    return new Proxy(Array(...args), { 
 
     get: function(target, property) { 
 
     console.log(target[property]); 
 
     return Reflect.get(target, property); 
 
     } 
 
    }); 
 
    } 
 
    Object.setPrototypeOf(LoggingArray, Array); 
 
    LoggingArray.prototype = Array.prototype; 
 
    return LoggingArray; 
 
})(Array); 
 

 
// Original code without array literal: 
 
var array = Array(1, 2, 3); 
 
var total = 0; 
 
for (var i in array) { 
 
    total += array[i] 
 
} 
 
console.log(total);

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