2014-12-10 3 views
2

Я знаю __defineGetter____defineSetter__) имя метода действительно weird and deprecated, но я нахожу это более удобно, чем Object.defineProperty. Сравнить себя:Object.prototype .__ defineGetter__ (и __defineSetter__) polyfill

//Readable 
Something.prototype.__defineGetter__("name", function() {return this._name;}); 
//Uh... - what? 
Object.defineProperty(Something.prototype, "name", { 
         get: function() {return this._name;} 
        }); 

Потому что, как я уже сказал, этот метод устарел. Так что я создаю polyfill, чтобы вернуть его в Bussiness:

if(!Object.prototype.__defineGetter__) { 
    Object.prototype.__defineGetter__ = function(name, func) { 
    Object.defineProperty(this, name, { 
     get: func 
    }); 
    } 
} 

Это действительно просто вызывает стандартную Object.defineProperty. Я мог бы назвать __defineGetter__ тем, что хотел. Я просто решил придерживаться того, что уже существовало.

Проблема заключается в том, что если я пользуюсь __defineGetter__ и __defineSetter__ полиполками на этом же имуществе, я звоню Object.defineProperty дважды.

Мой вопрос: согласен ли звонить Object.defineProperty дважды на том же объекте? Разве это не перезаписывает что-то, например?

+1

Да, это будет перезаписано. –

+0

IMHO: именно поэтому вы используете '.defineProperty' - вам не нужно писать отдельные методы для setter и getter. –

+0

@ArtyomNeustroev Иногда сеттер в любом случае не определен. Но я считаю, что '.defineProperty' более способный, но не очень читаемый. –

ответ

2

Чтобы сохранить старый set или get при повторном вызове defineProperty, вы должны вытащить их при добавлении геттер или сеттера:

var proto = Object.prototype; 

proto.__defineGetter__ = proto.__defineGetter__ || function(name, func) { 
    var descriptor = Object.getOwnPropertyDescriptor(this, name); 
    var new_descriptor = { get: func, configurable: true}; 
    if (descriptor) { 
     console.assert(descriptor.configurable, "Cannot set getter"); 
     if (descriptor.set) new_descriptor.set = descriptor.set; // COPY OLD SETTER 
    } 
    Object.defineProperty(this, name, new_descriptor); 
}; 

proto.__defineSetter__ = proto.__defineSetter__ || function(name, func) { 
    var descriptor = Object.getOwnPropertyDescriptor(this, name); 
    var new_descriptor = { set: func, configurable: true}; 
    if (descriptor) { 
     console.assert(descriptor.configurable, "Cannot set setter"); 
     if (descriptor.get) new_descriptor.get = descriptor.get; // COPY OLD GETTER 
    } 
    Object.defineProperty(this, name, new_descriptor); 
}; 
+0

Было бы лучше добавить '__defineGetter__' и' __defineSetter__' как неперечислимые, используя 'Object.defineProperty'. В противном случае это может быть проблематично в циклах 'for ... in'. – Oriol

0

Так что вам не нравится использовать defineProperty, который прекрасно , Однако тогда зачем даже использовать __defineGetter__ и __defineSetter__? На мой взгляд, это выглядит еще хуже.

В марте 2013 года у меня была такая же проблема с рвотного кода, поэтому я приготовил simple 41 LOC micro-library, который можно установить с помощью команды:

npm install dictionary 

Используя эту микро библиотеку можно определить методы получения и установки как это вместо:

Something.prototype.define({ 
    get name() { 
     return this._name; 
    }, 
    set name(_name) { 
     this._name = _name; 
    } 
}); 

Кроме того, он также позволяет создавать несчетные, нестираемые и постоянные свойства легко. Подробнее читайте в документации.

Если вы не хотите, чтобы эти дополнительные функции, а затем просто использовать:

Object.prototype.define = function (properties) { 
    if (Object.isExtensible(this)) { 
     var ownDescriptor = Object.getOwnPropertyDescriptor; 
     var defineProperty = Object.defineProperty; 
     var keys = Object.keys(properties); 
     var length = keys.length; 
     var index = 0; 

     while (index < length) { 
      var key = keys[index++]; 
      var descriptor = ownDescriptor(properties, key); 
      defineProperty(this, key, descriptor); 
     } 
    } 
}; 

Надежда, что помогает.