Как определить сеттер / геттер на прототипе


EDIT Oct 2016: обратите внимание, что этот вопрос был задан в 2012 году. Каждый месяц или около того кто-то добавляет новый ответ или комментарий, который опровергает ответ, но на самом деле не имеет смысла делать это, поскольку вопрос, вероятно, устарел (помните, что это было для Gnome Javascript для написания расширений gnome-shell, а не для браузера, что довольно специфично).

после мой предыдущий вопрос о том, как сделать подклассы в Javascript, я делаю подкласс суперкласса вот так:

function inherits(Child,Parent) {
    var Tmp = function {};
    Tmp.prototype = Parent.prototype;
    Child.prototype = new Tmp();
    Child.prototype.constructor = Child;
}
/* Define subclass */
function Subclass() {
    Superclass.apply(this,arguments);
    /* other initialisation */
}
/* Set up inheritance */
inherits(Subclass,Superclass);
/* Add other methods */
Subclass.prototype.method1 = function ... // and so on.

мой вопрос:как определить сеттер / геттер на прототипе с этим синтаксисом?

Я делал:

Subclass.prototype = {
    __proto__: Superclass.prototype,
    /* other methods here ... */

    get myProperty() {
        // code.
    }
}

но очевидно, что следующее не будет работать:

Subclass.prototype.get myProperty() { /* code */ }

Я использую GJS (GNOME Javascript), и движок должен быть более или менее таким же, как у Mozilla Spidermonkey. Мой код не предназначен для браузера, так как он поддерживается GJS (я думаю, что это означает Spidermonkey?), Я не возражаю, если это не кросс-совместимы.

5 69

5 ответов:

используя объявление литерала объекта (Самый простой способ):

var o = {
    a: 7,
    get b() {
        return this.a + 1;
    },
    set c(x) {
        this.a = x / 2
    }
};

используя Object.defineProperty (в современных браузерах, поддерживающих ES5):

Object.defineProperty(o, "myProperty", {
    get: function myProperty() {
        // code
    }
});

или через __defineGetter__ и __defineSetter__ ( устарел):

var d = Date.prototype;
d.__defineGetter__("year", function() { return this.getFullYear(); });
d.__defineSetter__("year", function(y) { this.setFullYear(y); });

использовать Object.defineProperty() on Subclass.prototype. Есть также __defineGetter__ и __defineSetter__ в некоторых браузерах, но они являются устаревшими. Для вашего примера это будет:

Object.defineProperty(Subclass.prototype, "myProperty", {
    get: function myProperty() {
        // code
    }
});

Я думаю, что вы хотели сделать таким образом:

function Unit() {
   	this._data; // just temp value
}
Unit.prototype = {
 	get accreation() {
   		return this._data;
   	},
   	set accreation(value) {
   		this._data = value
   	},
}
Unit.prototype.edit = function(data) {
   	this.accreation = data; // setting
   	this.out();
};

Unit.prototype.out = function() {
    alert(this.accreation); // getting
};

var unit = new Unit();
unit.edit('setting and getting');

function Field() {
    // children
}

Field.prototype = Object.create(Unit.prototype);

Field.prototype.add = function(data) {
  this.accreation = data; // setting
   	this.out();
}

var field1 = new Field();
field1.add('new value for getter&setter');

var field2 = new Field();
field2.out();// because field2 object has no setting

для определения сеттеры и геттеры "внутри прототипа объекта" вы должны сделать что-то вроде этого:

Object.defineProperties(obj.__proto__, {"property_name": {get: getfn, set: setfn}})

вы можете сократить это с помощью функции утилиты:

//creates get/set properties inside an object's proto
function prop (propname, getfn, setfn) {
    var obj = {};
    obj[propname] = { get: getfn, set: setfn };
    Object.defineProperties(this, obj);        
}

function Product () {
     this.name =  "Product";
     this.amount =  10;
     this.price =  1;
     this.discount =  0;
}

//how to use prop function
prop.apply(Product.prototype, ["total", function(){ return this.amount * this.price}]);

pr = new Product();
console.log(pr.total);

здесь мы используем опору.применить для установки контекстного продукта.прототип как "это", когда мы его называем.

С помощью этого кода Вы заканчиваете свойством get/set внутри прототипа объекта, а не экземпляра, как заданный вопрос.

(Проверено Firefox 42, Chrome 45)

укажите геттер или сеттер в конструкторах по объекту.defineProperty() метод. Этот метод принимает три аргумента: первый аргумент-это объект для добавления свойства, второй-имя свойства, и третий дескриптор объекта. Например, мы можем определить конструктор для нашего человек объект следующим образом:

var Employee = (function() {
    function EmployeeConstructor() {
        this.first = "";
        this.last = "";
        Object.defineProperty(
            this,
            "fullName", {
                get: function() {
                    return this.first + " " +
                        this.last;
                },
                set: function(value) {
                    var parts = value.toString().split(" ");
                    this.name = parts[0] || "";
                    this.last = parts[1] || "";
                }
            });
    }
    return
    EmployeeConstructor;
}());

Использование Объекта.defineProperty() дает больше контроля над определением нашей собственности. Например, мы можем указать, если свойство мы описание может быть динамически удалено или переопределено, если его значение может быть изменено, и т. д на.

мы можем такие ограничения, установив следующие свойства объекта дескриптора:

  • writable: это логическое значение, которое говорит, является ли значение свойство может быть изменено; его значение по умолчанию-false
  • настраивается: это логическое значение, которое говорит, является ли свойство дескриптор может быть изменен или само свойство может быть удалено; свой значение по умолчанию-false
  • enumerable: это логическое значение, указывающее, может ли свойство быть попасть в цикл по свойствам объекта; его значение по умолчанию ложь
  • значение: это представляет значение, связанное со свойством; его значение по умолчанию не определено