2015-11-09 19 views
5

È possibile definire un prototipo solo per {} -Objects?Definire il prototipo solo per gli oggetti {...}

In Javascript, quasi tutto è un oggetto.

Object.prototype.test = function() { 
    alert("test"); 
} 

Tutti gli oggetti (compresi numeri, stringhe e array) avranno questo metodo. Ma lo voglio solo per un oggetto struct. > {...} <

È possibile prima creare tutti i prototipi per l'oggetto ed eliminarlo da altri come Numero, String e Array.

// Overwrite 
Array.prototype.test = undefined; // or delete property 

Questo "funziona" ... Il prototipo viene sovrascritto. Ma la chiave esiste ancora.

// Show all keys 
for (key in arr) 
{ 
    alert(key); // print index of array AND keynames 
} 

Sto cercando il modo più elegante per farlo.

+4

Non modificare il prototipo 'Object' a meno che non si intende la proprietà di essere disponibile su ogni oggetto, che lei ha dichiarato che non vuoi. Indipendentemente da ciò, la modifica del prototipo 'Object' è quasi sempre una cattiva idea. Invece, dovresti posizionare la proprietà sul prototipo di una classe che controlli e ereditare da quella necessaria. –

+0

Inoltre, l'eliminazione della proprietà dal prototipo 'Array' non farà ciò che si desidera. Chiamando 'test' su un array verrà comunque eseguita la funzione, perché salirà la catena del prototipo e la chiamata semplice' test' sul prototipo 'Object': http://jsfiddle.net/x2wysox8/ –

+0

non elimina la proprietà 'test' da' Array.prototype', basta lanciare un errore su chiamata, se si desidera limitare l'accesso al metodo 'Object.prototype.test'. Ma aggiungere metodi a 'Object.prototype' è una cattiva pratica, e pensateci due volte, prima di fare questo –

risposta

0

con Array.prototype.test = undefined; il valore dei metodi impostato su undefinied e questo non lo eliminerà.

Se davvero vuole cancellare il metodo (proprietà) utilizzare delete Array.prototype.test;

P.S. Ma in questo caso (con oggetto {}) -> non puoi ottenere ciò che desideri con delete.

Array.prototype è ereditato da Object.prototype, e dopo l'eliminazione Array.prototype.test il codice troverà Object.prototype.test e chiamarlo.

Penso che il modo migliore per fare ciò che si vuole è quello di fare qualcosa di simile:

Object.defineProperty(Object.prototype, 'test', { 
    enumerable: false, 
    configurable: false, 
    writable: true, 
    value: function(test) { alert('In test' + test); } 
}); 

Object.defineProperty(Array.prototype, 'test', { 
    enumerable: false, 
    configurable: false, 
    writable: false, 
    value: function() { throw new Error('You can\'t do it!'); } 
}); 

try { 
    var a = []; 
    var keys = ""; 

    for (key in a) { 
     keys += key + ', '; // get all keys 
    } 
    // call array test method -> will throw exception 
    a.test('from array'); 

} catch (e) { 
    // check keys -> test is not here 
    console.log("Error: " + e.message + ' ' + "KEYS: " + keys); 
} 

var b = {}; 
// and this will work 
b.test('from object'); 
+2

Ciò non impedirà che 'test' venga richiamato su' Array'. La catena del prototipo troverà la funzione 'test' sul prototipo' Object' e la chiamerà: http://jsfiddle.net/x2wysox8/ –

0

bene anche se è possibile modificare prototipo oggetto, questo è altamente sconsigliato. Questo perché tutte le librerie che userai mai si aspettano che Object sia intatto. Ciò può portare a tracciare bug e comportamenti imprevisti da parte di alcune librerie.

Ciò di cui hai bisogno è imparare come eseguire l'orientamento corretto degli oggetti in JS. Questo è un argomento molto confuso per gli antipasti di js. Ti raccomando di leggere l'eccellente "I principi del JavaScript orientato agli oggetti" di Nicolas Zakas e la serie di libri "Tu non conosci JS" di Kyle Simpson.

Ma si può avere un buon inizio con la mia spiegazione su come fare Object Orientation in javascript nel mio blog: http://www.ideasaboutcode.com/object-orientation-in-javascript/

Speranza che aiuta.

2

Quasi certamente non si desidera modificare il prototipo Object. Questo MDN article on JavaScript inheritance riassume bene:

One mis-funzione che viene spesso utilizzato è quello di estendere Object.prototype o uno degli altri prototipi incorporati.

Questa tecnica si chiama patch per scimmia e interrompe l'incapsulamento. Sebbene utilizzato da framework popolari come Prototype.js, non esiste ancora una buona ragione per ingombrare i tipi incorporati con funzionalità aggiuntive non standard.

Nel tuo esempio, rimuovendo la proprietà test da Array non avranno l'effetto desiderato. Quando viene chiamato il numero Array.test, cercherà semplicemente la catena del prototipo ed eseguirà Object.test. Questo è illustrato dal seguente codice:

Object.prototype.test = function() { 
    alert('In test'); 
} 

delete Array.prototype.test; 

//Calls Object.test and shows the alert 
[].test(); 

Invece, si potrebbe creare una classe di base che è possibile controllare e di ereditare da essa, se necessario. Vedi sotto per una dimostrazione di lavoro.

function MyBaseClass() { 
 
    this.test = function() { 
 
    log('In test'); 
 
    }; 
 
} 
 

 
function Shape() { 
 
    this.shapeAction = function() { 
 
    log('Shape action'); 
 
    }; 
 
} 
 

 
Shape.prototype = new MyBaseClass(); 
 

 
function Square() { 
 
    this.squareAction = function() { 
 
    log('Square action'); 
 
    this.shapeAction(); 
 
    }; 
 
} 
 

 
Square.prototype = new Shape(); 
 

 
//Test function can be called on Square, but not on Array 
 
var s = new Square(); 
 

 
s.squareAction(); 
 
s.shapeAction(); 
 
s.test(); 
 

 
try { 
 
    [].test(); 
 
} 
 
catch (e) { 
 
    log('Exception when trying to run Array.test: ' + e); 
 
} 
 

 
//Log function for demonstration purposes 
 
function log(s) { 
 
    var e = document.createElement('p'); 
 
    e.innerHTML = s; 
 
    document.body.appendChild(e); 
 
}

Problemi correlati