如何在原型上定义setter/getter

mat*_*fee 73 javascript getter

编辑2016年10月:请注意这个问题是在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.
Run Code Online (Sandbox Code Playgroud)

我的问题是,如何使用这种语法在原型上定义一个setter/getter?

我曾经做过:

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

    get myProperty() {
        // code.
    }
}
Run Code Online (Sandbox Code Playgroud)

但显然以下方法不起作用:

Subclass.prototype.get myProperty() { /* code */ }
Run Code Online (Sandbox Code Playgroud)

我正在使用GJS(GNOME Javascript),并且该引擎与Mozilla Spidermonkey一样或多或少相同.我的代码不适用于浏览器,只要GJS支持它(我猜这意味着Spidermonkey?),我不介意它是不是交叉兼容的.

Ber*_*rgi 94

使用Object.defineProperty()Subclass.prototype.也有__defineGetter____defineSetter__可在某些浏览器,但他们已被弃用.对于你的例子,它将是:

Object.defineProperty(Subclass.prototype, "myProperty", {
    get: function myProperty() {
        // code
    }
});
Run Code Online (Sandbox Code Playgroud)

  • @bob不确定你的评论是什么意思.当然,如果你想动态获取持续时间,你需要一个getter,但它可以在其他属性上运行,就像所有其他方法一样:`Object.defineProperty(...,"duration",{get:function(){return this .end - this.begin;}});` (2认同)

bfa*_*tto 66

使用对象文字声明(最简单的方法):

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

使用Object.defineProperty(在支持ES5的现代浏览器上):

Object.defineProperty(o, "myProperty", {
    get: function myProperty() {
        // code
    }
});
Run Code Online (Sandbox Code Playgroud)

或使用__defineGetter____defineSetter__(DEPRECATED):

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


小智 33

我想你想这样做:

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
Run Code Online (Sandbox Code Playgroud)

  • 当你像这样覆盖`Unit.prototype`时,`Unit.prototype.constructor`会被删除.我很喜欢这个解决方案.也许你可以做`Object.assign(Unit.prototype,{get accreation(){...}});`. (6认同)
  • 惊人.唯一正确的答案是没有投票.除非你必须遭受旧IE的侮辱,否则有ZERO使用`Object.defineProperty`的理由. (2认同)

Mac*_*ken 5

要在对象的原型内部定义setter和getter,您必须执行以下操作:

Object.defineProperties(obj.__proto__, {"property_name": {get: getfn, set: setfn}})
Run Code Online (Sandbox Code Playgroud)

您可以使用实用程序功能将其简化:

//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);
Run Code Online (Sandbox Code Playgroud)

在这里,当我们调用它时,我们使用prop.apply将上下文Product.prototype设置为“ this”。

使用此代码,您将在对象的原型(而不是实例)中获得一个get / set属性,而不是问题所要求的实例。

(经过测试的Firefox 42,Chrome 45)