2012-07-05 24 views
32

मैं Array.Add() के बजाय Array.push() आदि जैसे कुछ उपयोगकर्ता के अनुकूल तरीकों के साथ जावास्क्रिप्ट में सरणी वस्तु का विस्तार करने की कोशिश ...तरीके सरणी वस्तु जावास्क्रिप्ट में

विस्तार करने के लिए मैं यह करने के लिए 3 तरीके को लागू । दुर्भाग्य से तीसरा तरीका काम नहीं कर रहा है और मैं पूछना चाहता हूं क्यों? और यह कैसे काम करते हैं।

//------------- 1st way 
Array.prototype.Add=function(element){ 
    this.push(element); 
}; 

var list1 = new Array(); 
list1.Add("Hello world"); 
alert(list1[0]); 

//------------- 2nd way 
function Array2() { 
    //some other properties and methods 
}; 

Array2.prototype = new Array; 
Array2.prototype.Add = function(element){ 
    this.push(element); 
}; 

var list2 = new Array2; 
list2.Add(123); 
alert(list2[0]); 

//------------- 3rd way 
function Array3() { 
    this.prototype = new Array; 
    this.Add = function(element){ 
     this.push(element); 
    }; 
}; 

var list3 = new Array3; 
list3.Add(456); //push is not a function 
alert(list3[0]); // undefined 

तीसरे तरीके से मैं आंतरिक रूप से ऐरे ऑब्जेक्ट को ऐरे ऑब्जेक्ट का विस्तार करना चाहता हूं। ऐसा कैसे करें ताकि "पुश एक फ़ंक्शन नहीं है" और "अपरिभाषित" न हो?

यहां मैं चौथा रास्ता जोड़ता हूं।

//------------- 4th way 
function Array4() { 
    //some other properties and methods 
    this.Add = function(element){ 
     this.push(element); 
    }; 
}; 
Array4.prototype = new Array(); 

var list4 = new Array4(); 
list4.Add(789); 
alert(list4[0]); 

यहां फिर से मुझे प्रोटोटाइप का उपयोग करना होगा। मुझे उम्मीद है कि क्लास कन्स्ट्रक्टर के बाहर अतिरिक्त लाइनों का उपयोग Array4.prototype के रूप में करने से बचें। मैं एक ही स्थान पर सभी टुकड़ों के साथ एक कॉम्पैक्ट परिभाषित कक्षा चाहता था। लेकिन मुझे लगता है कि मैं इसे अन्यथा नहीं कर सकता।

+0

आप सरणी के लिए एक विधि जोड़ देते हैं तो आप सरणियों – SpacedMonkey

+0

आप कॉफी स्क्रिप्ट में देखा है पर foreach() टूट जाएगा? मैं एक उदाहरण – SMathew

+0

के साथ अपना उत्तर अपडेट करूंगा, मैं पहले उदाहरण में Array.prototype के लिए कोई विधि नहीं जोड़ूंगा। यह एक परीक्षण था। मैं एक कक्षा तैयार करूंगा जो ऐरे ऑब्जेक्ट का विस्तार करेगी। उदाहरण के लिए जेएसएरे। जेएसएरे ऑब्जेक्ट्स Arrays होंगे लेकिन अधिक सुविधाओं के साथ। – demosthenes

उत्तर

27

विधि नाम लोअरकेस होना चाहिए। प्रोटोटाइप को कन्स्ट्रक्टर में संशोधित नहीं किया जाना चाहिए।

function Array3() { }; 
Array3.prototype = new Array; 
Array3.prototype.add = Array3.prototype.push 
CoffeeScript में

class Array3 extends Array 
    add: (item)-> 
    @push(item) 

आपको लगता है कि वाक्य रचना पसंद नहीं है, और आप इसे निर्माता के भीतर से विस्तार करने के लिए है, आपका ही एकमात्र विकल्प है:

// define this once somewhere 
// you can also change this to accept multiple arguments 
function extend(x, y){ 
    for(var key in y) { 
     if (y.hasOwnProperty(key)) { 
      x[key] = y[key]; 
     } 
    } 
    return x; 
} 


function Array3() { 
    extend(this, Array.prototype); 
    extend(this, { 
     Add: function(item) { 
     return this.push(item) 
     } 

    }); 
}; 

आप यह भी कर सकता है

ArrayExtenstions = { 
    Add: function() { 

    } 
} 
extend(ArrayExtenstions, Array.prototype); 



function Array3() { } 
Array3.prototype = ArrayExtenstions; 

पुराने दिनों में, 'prototype.js' में क्लास.क्रेट विधि होती थी।तुम्हें पता है, लपेट कर सकता है यह सब है कि

var Array3 = Class.create(Array, { 
    construct: function() { 

    },  
    Add: function() { 

    } 
}); 

इस बारे में अधिक जानकारी के लिए और कैसे लागू करने के लिए के लिए की तरह एक विधि है prototype.js स्रोत कोड

+0

हाँ यह दूसरा तरीका है। मैं प्रयोजन में उपयोग करता हूं इसके बदले में जोड़ें क्योंकि मैं विज़ुअल मूल रूप और अनुभव जैसे कुछ विस्तार विधियों को लिखना चाहता हूं। – demosthenes

+0

ठीक है मैं कन्स्ट्रक्टर के अंदर प्रोटोटाइप का उपयोग नहीं कर सकता। क्या कन्स्ट्रक्टर के अंदर ऐरे ऑब्जेक्ट का विस्तार करने का कोई तरीका है? – demosthenes

+1

हां, लेकिन अगर आपको बहुत सारी वस्तुओं को तुरंत चालू करना है तो यह महंगा है। एक उदाहरण कार्यान्वयन के लिए http://api.jquery.com/jQuery.extend/ देखें। उस तकनीक का उपयोग कर आप कर सकते हैं। फ़ंक्शन Array3() {विस्तार (यह, {जोड़ें: फ़ंक्शन (आइटम) {इस.push (आइटम)}}}}; – SMathew

2

अपने तीसरे उदाहरण में आप ऑब्जेक्ट Array3 ऑब्जेक्ट के लिए prototype नामक एक नई संपत्ति बना रहे हैं। जब आप new Array3 करते हैं जो new Array3() होना चाहिए, तो आप उस ऑब्जेक्ट को परिवर्तनीय list3 में तत्काल कर रहे हैं। इसलिए, Add विधि काम नहीं करेगी क्योंकि this, जो प्रश्न में वस्तु है, में वैध विधि push नहीं है। उम्मीद है आप समझ गए होंगे।

संपादित करें: के बारे में अधिक जानने के लिए Understanding JavaScript Context देखें।

+0

मुझे लगता है, यह। प्रोटीोटाइप को ऐरे 3 की संपत्ति के रूप में माना जाता है, धन्यवाद – demosthenes

+1

जब आप ऑब्जेक्ट को तुरंत चालू करते हैं तो '()' को जोड़ना न भूलें। 'ऐरे' भी एक वस्तु है इसलिए 'नया ऐरे() '(या टिपिक रूप से बस' []')। यह काम करता है क्योंकि ब्राउज़र स्मार्ट हो रहे हैं। टिप elclanrs के लिए – elclanrs

+0

ठीक है, मैं जोड़ देगा() धन्यवाद :) अब मैं सिर्फ जे एस के बारे में कुछ नई बातें जानने के लिए – demosthenes

0

क्या आप कुछ और जटिल करने की कोशिश कर रहे हैं तो बस "जोड़ें" नामक "पुश" के लिए उपनाम जोड़ें?

यदि नहीं, तो यह संभवतः ऐसा करने से बचने के लिए सबसे अच्छा होगा। कारण यह है कि मैं यह सुझाव देता हूं कि यह एक बुरा विचार है कि चूंकि ऐरे एक अंतर्निहित जावास्क्रिप्ट प्रकार है, इसलिए इसे संशोधित करने से ऐरे के प्रकार में आपकी नई "जोड़ें" विधि हो जाएगी। किसी अन्य तीसरे पक्ष के साथ नाम संघर्ष की संभावना अधिक है और तृतीय पक्ष स्क्रिप्ट को आपके पक्ष में अपनी विधि खोने का कारण बन सकता है।

मेरा सामान्य नियम ऐरे पर काम करने के लिए एक सहायक कार्य करना है यदि यह पहले से मौजूद नहीं है और केवल अत्यधिक आवश्यक है तो केवल ऐरे का विस्तार करें।

+0

। मैं जेएस के लिए Visual Basic कोर फ़ंक्शंस की तरह दिखने के लिए कुछ विस्तार विधियां लिखना चाहता हूं। यह वेब परियोजनाओं को लिखने में मेरे लिए अधिक उपयुक्त और आसान है। – demosthenes

+0

एक महान अभ्यास की तरह लगता है! बस आपको जेएस सीखने की जरूरत है। – elclanrs

+0

बेशक मैं इसे एक अलग नामस्थान – demosthenes

0

आप जावास्क्रिप्ट में सरणी वस्तु विस्तार नहीं कर सकते में है।

इसके बजाय, आप क्या कर सकते हैं एक ऑब्जेक्ट को परिभाषित करता है जिसमें ऐरे पर किए गए कार्यों की एक सूची होगी, और इन कार्यों को उस ऐरे इंस्टेंस में इंजेक्ट करें और इस नए ऐरे इंस्टेंस को वापस कर दें। आपको सूची में अपने कस्टम फ़ंक्शंस को शामिल करने के लिए Array.prototype को बदलना नहीं चाहिए।

उदाहरण:

function MyArray() { 
    var tmp_array = Object.create(Array.prototype); 
    tmp_array = (Array.apply(tmp_array, arguments) || tmp_array); 
    //Now extend tmp_array 
    for(var meth in MyArray.prototype) 
    if(MyArray.prototype.hasOwnProperty(meth)) 
     tmp_array[meth] = MyArray.prototype[meth]; 
    return (tmp_array); 
} 
//Now define the prototype chain. 
MyArray.prototype = { 
    customFunction: function() { return "blah blah"; }, 
    customMetaData: "Blah Blah", 
} 

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

+0

मुझे लगता है कि 'प्रोटोटाइप' असाइन करने के लिए यह खराब प्रथा है। मौजूदा 'प्रोटोटाइप' ऑब्जेक्ट के गुणों को असाइन करना हमेशा बेहतर होता है। – jchook

+1

आप कहते हैं कि आप ऐरे ऑब्जेक्ट का विस्तार नहीं कर सकते हैं लेकिन स्वीकार करते हैं कि Array.prototype में फ़ंक्शंस जोड़ना संभव है ... आपका उत्तर मेरे लिए विरोधाभासी प्रतीत होता है – Purefan

+1

@Purefan - यह विरोधाभासी हो सकता है, लेकिन यह जावास्क्रिप्ट को समझने में सहायता करता है (और नहीं करता) करते हैं - जो जेएस दुनिया के बाहर से लोगों के प्रति उलझन में है। –

9

ES6

class SubArray extends Array { 
    constructor(...args) { 
     super(...args); 
    } 
    last() { 
     return this[this.length - 1]; 
    } 
} 
var sub = new SubArray(1, 2, 3); 
sub // [1, 2, 3] 
sub instanceof SubArray; // true 
sub instanceof Array; // true 

Using __proto__

function SubArray() { 
    var arr = [ ]; 
    arr.push.apply(arr, arguments); 
    arr.__proto__ = SubArray.prototype; 
    return arr; 
} 
SubArray.prototype = new Array; 

अब आप SubArray

करने के लिए अपने तरीकों में जोड़ सकते हैं (पुराने जवाब है, की सिफारिश नहीं की, performance issues कारण हो सकता है)
SubArray.prototype.last = function() { 
    return this[this.length - 1]; 
}; 

प्रारंभ सामान्य सरणी की तरह

var sub = new SubArray(1, 2, 3); 

बर्ताव करता है सामान्य सरणी

sub instanceof SubArray; // true 
sub instanceof Array; // true 
+1

'__proto__' का उपयोग करते समय अधिकांश जावास्क्रिप्ट कार्यान्वयन में समर्थित है, यह एक मानक सुविधा नहीं थी जब तक कि es6 में विरासत सुविधा के रूप में चिह्नित नहीं किया जाता। यदि भारी मात्रा में उपयोग किया जाता है तो यह प्रदर्शन समस्याओं का कारण बन सकता है। इसका उपयोग करना आम तौर पर एक बुरा विचार है। – Insomniac

+0

@ टीबीओटीवी 63 सहमत हुए। ईएस 6 में आप आसानी से एक ऐरे वर्ग का विस्तार कर सकते हैं।मेरे उत्तर – laggingreflex

+1

को अपडेट किया गया है, आपको अपने 'कन्स्ट्रक्टर' में 'सुपर' में मानों को पास करना चाहिए, जैसे: 'कन्स्ट्रक्टर (... आइटम) {सुपर (... आइटम)} ' –

0

एक समय पहले मैं किताब जावास्क्रिप्ट निंजाजॉन द्वारा लिखित पढ़ तरह Resig, के निर्माता jQuery। उन्होंने एक सादे वस्तु के साथ सरणी जैसी विधियों की नकल करने का एक तरीका प्रस्तावित किया। असल में केवल length आवश्यक है।

var obj = { 
    length: 0, 
    add: function(elem){ 
     Array.prototype.push.call(this, elem); 
    }, 
    filter: function(callback) { 
     return Array.prototype.filter.call(this, callback); //or provide your own implemetation 
    } 
}; 

obj.add('a'); 
obj.add('b'); 
console.log(obj.length); //2 
console.log(obj[0], obj[1]); //'a', 'b' 

मेरा मतलब यह अच्छा या बुरा नहीं है। यह Array संचालन करने का एक मूल तरीका है। लाभ यह है कि आप Array prototype का विस्तार नहीं करते हैं। ध्यान रखें कि obj एक सादा object है, यह Array नहीं है। इसलिए obj instanceof Arrayfalse वापस आ जाएगा। obj को façade के रूप में सोचें।

यदि वह कोड आपके लिए ब्याज है, तो अंश लिस्टिंग 4.10 पढ़ें सरणी जैसी विधियों को सिमुलेट करना

1

तुम भी ES6 में इस तरह से उपयोग कर सकते हैं:

Object.assign(Array.prototype, { 
    unique() { 
     return this.filter((value, index, array) => { 
     return array.indexOf(value) === index; 
     }); 
    } 
}); 

परिणाम:

let x = [0,1,2,3,2,3]; 
let y = x.unique(); 
console.log(y); // => [0,1,2,3] 
+0

यह ऐरे प्रोटोटाइप को बढ़ाता है और नहीं किया जाना चाहिए (क्योंकि यह पूरी साइट को प्रभावित करता है) –

0
var SubArray = function() {           
    var arrInst = new Array(...arguments); // spread arguments object 
    /* Object.getPrototypeOf(arrInst) === Array.prototype */ 
    Object.setPrototypeOf(arrInst, SubArray.prototype);  //redirectionA 
    return arrInst; // now instanceof SubArray 
}; 

SubArray.prototype = { 
    // SubArray.prototype.constructor = SubArray; 
    constructor: SubArray, 

    // methods avilable for all instances of SubArray 
    add: function(element){return this.push(element);}, 
    ... 
}; 

Object.setPrototypeOf(SubArray.prototype, Array.prototype); //redirectionB 

var subArr = new SubArray(1, 2); 
subArr.add(3); subArr[2]; // 3 

जवाब एक कॉम्पैक्ट समाधान का जो रूप में सभी समर्थन ब्राउज़रों में अपेक्षित तरीके से काम करता है।

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