If I use get
with defineProperty
Object.defineProperty(Object.prototype,'parent',{
get:function(){return this.parentNode}
});
and I can call it like: document.body.parent
, then it works.
When I use value
with 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
}
});
I can call it like: document.getElementsByName("newtag").parent(2)
, means to find the parent node of newtag's parent node.
But when I put them together it says Uncaught TypeError: Invalid property. A property cannot both have accessors and be writable or have a value
.
How can I do it so that I can call it both ways, .parent
& .parent(n)
?
No jQuery
MDN describes the reason for the error
Property descriptors present in objects come in two main flavors: data descriptors and accessor descriptors. A data descriptor is a property that has a value, which may or may not be writable. An accessor descriptor is a property described by a getter-setter pair of functions. A descriptor must be one of these two flavors; it cannot be both.
There is reason for this: the way you want would be ambiguous: if parent()
was a function, then parent
would return that function and the getter?
Also do not change object that you don't own. Such code would not be maintainable: if someone would define its own Object.prototype.parent()
in his library, you could not use it. Prior to any use of any code, you would need to track down what was changed. This would be the same effort as writing everything from scratch.
Object.prototype
is particularly bad idea to change: by the prototype you add the parent()
function to every array, JSON object, webAPI objects... they don't have parentNode
, so that function is completely useless to them, it is just a performance burden.
The previous two paragraphs are the reason why we have Object.defineProperty
and not Object.prototype.defineProperty
. Note that if it would be so, you could code myAPI.defineproperty(...)
in the code below, which is shorter, BUT... the performance and the design... schrecklich.
You could code something like this
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
but I doubt it would be useful.