2013-06-16 6 views
0

Если я использую get с definePropertyиспользование defineProperty получить и значение вместе

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

и я могу назвать это нравится: document.body.parent, то он работает.

Когда я использую value с 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 
    } 
}); 

Я могу назвать это нравится: document.getElementsByName("newtag").parent(2), значит найти родительский узел родительского узла новыйТег в.

Но когда я их собрал, он говорит Uncaught TypeError: Invalid property. A property cannot both have accessors and be writable or have a value.

Как это сделать, чтобы я мог назвать это в обоих направлениях, .parent & .parent(n)?

Нет JQuery

+1

Я знаю, что это не в тему, но почему вы расширяете 'Object.prototype', чтобы улучшить элементы DOM? Не представляется полезным добавлять DOM-ориентированные методы к * всем * объектам. –

+0

@CrazyTrain Я понимаю вашу озабоченность ... но все, что я делаю, необходимо ... – NazKazi

+0

@BlackCobra: Нет, вы не можете создать значение, являющееся как узлом DOM, так и функцией. И это даже не связано с смешиванием дескрипторов свойств доступа и данных. Скажите, пожалуйста, [что ваша фактическая проблема] (http://meta.stackexchange.com/q/66377) - что вам понадобится для этого странного расширения DOM для - и мы могли бы предложить лучшее решение. – Bergi

ответ

0

MDN описывает причину ошибки

дескрипторы собственности, присутствующие в объектах в двух основных вариантах: данные дескрипторов и аксессоры дескрипторы. Дескриптор данных - это свойство , которое имеет значение, которое может быть или не быть доступно для записи. Дескриптор доступа - это свойство, описываемое парой установочных коэффициентов из . Дескриптор должен быть одним из этих двух вариантов; не может быть обе.

Существует причина для этого: так, как вы хотите, будет неоднозначным: если parent() была функция, то parent бы вернуть эту функцию и-газопоглотитель?

также не изменяйте объект, который вам не владеет. Такой код не подлежит ремонту: если кто-то определит свой собственный Object.prototype.parent() в своей библиотеке, вы не сможете его использовать. Перед любым использованием любого кода вам нужно будет отследить, что было изменено. Это будет то же самое, что писать все с нуля.

Object.prototype особенно плохая идея изменить: по прототипу добавить функцию parent() для каждого массива, объект JSON, webAPI объектов ... они не имеют parentNode, так что функция совершенно бесполезна для них, это просто бремя производительности.

Предыдущие два абзаца являются причиной того, что у нас есть Object.defineProperty, а не Object.prototype.defineProperty. Обратите внимание: если это так, вы можете ввести код myAPI.defineproperty(...) в код ниже, который короче, НО ... производительность и дизайн ... schrecklich.

Вы могли кодировать что-то вроде этого

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 

, но я сомневаюсь, что это было бы полезно.

0

Нет, вы не можете, к сожалению. Вместо этого вы можете создать немного другую функцию, которая возвращает первый parentNode по умолчанию (если не указан параметр), в противном случае он учитывает n родителей.

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; 
}; 

Некоторые замечания: во-первых, вы должны проверить, если объект имеет свойство ParentNode, в противном случае скрипт вызовет исключение. Я использовал hasOwnProperty, но вы можете удалить эту строку, если вы распространяете только HTMLElement.

Кроме того, если n равно 0 или 1, или оно не определено, оно возвращает родительский элемент элемента. Используйте его как element.parent() или element.parent(2).

+0

первый - это ключ ... не функция ... '.parent' ... вторая - это функция ...' .parent (n) '... но вы создаете функцию для обоих ... Мне нужен ключ и функция с тем же именем и как прототип 'Object' ... – NazKazi

+1

« Нет, вы не можете, к сожалению. [...] « –

+0

Я думаю, что есть способ сделать это. .. может быть, не используя 'defineProperty' ... но есть что-то ... – NazKazi