2013-06-16 2 views
0

Si je get avec definePropertyutilisation DefineProperty obtenir et de la valeur ainsi que

Object.defineProperty(Object.prototype,'parent',{ 
    get:function(){return this.parentNode} 
}); 

et je peux l'appeler comme: document.body.parent, il fonctionne.

Lorsque j'utilise value avec defineProperty

Object.defineProperty(Object.prototype,'parent',{ 
    value:function(x){ 
     var temp=this.parentNode; 
     for(var i=1;i<x;i++){temp=temp.parentNode}; 
     return temp 
    } 
}); 

Je peux l'appeler comme: document.getElementsByName("newtag").parent(2), signifie pour trouver le nœud parent du nœud parent de newTag.

Mais quand je les ai mis ensemble il est dit Uncaught TypeError: Invalid property. A property cannot both have accessors and be writable or have a value.

Comment puis-je faire pour que je puisse appeler dans les deux sens, .parent & .parent(n)?

Pas jQuery

+1

Je sais que c'est hors sujet, mais pourquoi étendez-vous 'Object.prototype' afin d'améliorer les éléments DOM? Il ne semble pas utile d'ajouter des méthodes DOM-centric à * tous * les objets. –

+0

@CrazyTrain Je comprends votre préoccupation ... mais tout ce que je fais est nécessaire ... – NazKazi

+0

@BlackCobra: Non, vous ne pouvez pas créer une valeur qui est à la fois un nœud DOM et une fonction. Et ce n'est même pas quelque chose à faire avec le mélange de descripteurs d'accesseur et de propriétés de données. S'il vous plaît dites-nous [quel est votre problème réel] (http://meta.stackexchange.com/q/66377) - ce que vous auriez besoin de cette extension DOM étrange pour - et nous pourrions être en mesure de proposer une meilleure solution. – Bergi

Répondre

0

MDN décrit la raison de l'erreur

descripteurs de propriété présents dans les objets sont disponibles en deux saveurs principales: données descripteurs et les descripteurs accesseurs. Un descripteur de données est une propriété qui a une valeur, qui peut être inscriptible ou non. Un descripteur accesseur est une propriété décrite par une paire getter-setter de fonctions. Un descripteur doit être l'un de ces deux arômes; il ne peut pas être les deux.

Il y a des raisons pour cela: la façon dont vous voulez serait ambiguë: si parent() était une fonction, alors parent retournera cette fonction et le getter?

Egalement ne changez pas d'objet que vous ne possédez pas. Un tel code ne serait pas maintenable: si quelqu'un définissait son propre Object.prototype.parent() dans sa bibliothèque, vous ne pourriez pas l'utiliser. Avant toute utilisation d'un code, vous devez rechercher ce qui a été modifié. Ce serait le même effort que d'écrire tout à partir de zéro.

Object.prototype est particulièrement mauvaise idée de changer: le prototype que vous ajoutez la fonction parent() à chaque tableau, objet JSON, webAPI objets ... ils n'ont parentNode, de sorte que la fonction est complètement inutile pour eux, il est juste un fardeau de performance. Les deux paragraphes précédents sont la raison pour laquelle nous avons Object.defineProperty et non Object.prototype.defineProperty. Notez que si c'était le cas, vous pourriez coder myAPI.defineproperty(...) dans le code ci-dessous, ce qui est plus court, MAIS ... la performance et le design ... schrecklich.

Vous pouvez coder quelque chose comme ça

var myAPI = { 
    node: document.body, 
    level: 1 
}; 

Object.defineProperty(MyAPI,'parent',{ 
    get:function(){ 
     var temp=MyAPI.node.parentNode; 
     // some sanity check should be performed here 
     for(var i=1;i<MyAPI.level;i++){temp=temp.parentNode}; 
     return temp; 
    } 
}); 

myAPI.node = document.getElementById("myNode"); 
myAPI.level = 2; 
var grandFather = myAPI.parent; // actually returns the grandparent 

mais je doute qu'il serait utile.

0

Non, vous ne pouvez pas malheureusement. Au lieu de cela, vous pouvez créer une fonction légèrement différente qui retourne le premier parentNode par défaut (si aucun paramètre n'est spécifié), sinon il compte n parents.

Object.prototype.parent = function (n) { 
    if (!this.hasOwnProperty('parentNode')) return null; 
    if (!n || n === 1) return this.parentNode; 
    var temp = this.parentNode; 
    for (var i = 1; i < n; i++) 
     temp = temp.parentNode; 
    return temp; 
}; 

Quelques notes: tout d'abord, vous devez vérifier si l'objet a un parentNode de propriété, sinon le script déclenche une exception. J'ai utilisé hasOwnProperty, mais vous pouvez supprimer cette ligne si vous étendez simplement HTMLElement.

De même, si n vaut 0 ou 1, ou s'il n'est pas défini, il retournera le parentNode de l'élément. Utilisez-le comme element.parent() ou element.parent(2).

+0

le premier est une clé ... pas une fonction ... '.parent' ... la seconde est une fonction ...' .parent (n) '... mais vous créez une fonction pour les deux ... J'ai besoin d'une clé et d'une fonction avec le même nom et comme prototype de 'Object' ... – NazKazi

+1

" Non, vous ne pouvez malheureusement pas. [...] " –

+0

Je pense qu'il y a un moyen de faire cela. .. peut-être pas en utilisant 'defineProperty' ... mais il y a quelque chose ... – NazKazi

Questions connexes