编辑 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.
我的问题是,如何使用此语法在原型上定义二传手/getter?
我曾经做过:
Subclass.prototype = {
__proto__: Superclass.prototype,
/* other methods here ... */
get myProperty() {
// code.
}
}
但显然以下内容不起作用:
Subclass.prototype.get myProperty() { /* code */ }
我使用的是GJS(GNOME Javascript(,引擎或多或少与Mozilla Spidermonkey相同。我的代码不适用于浏览器,所以只要GJS支持它(我想这意味着蜘蛛猴?(,我不介意它是否交叉兼容。
在 Subclass.prototype
上使用 Object.defineProperty()
。某些浏览器上也有可用的__defineGetter__
和__defineSetter__
,但它们已被弃用。对于您的示例,它将是:
Object.defineProperty(Subclass.prototype, "myProperty", {
get: function myProperty() {
// code
}
});
使用对象文字声明(最简单的方法(:
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); });
我想你想这样做:
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
要在"对象的原型中"定义 setter 和 getter,您必须执行以下操作:
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);
在这里,我们使用 prop.apply 将上下文 Product.prototype 设置为"this"。
使用此代码,您可以在对象的原型中以 get/set 属性结束,而不是问题所问的实例。
(测试火狐 42, 铬 45(
通过 Object.defineProperty(( 方法在构造函数中指定 getter 或 setter。此方法采用三个参数:第一个参数是要将属性添加到的对象,第二个是属性的名称,并且第三个是属性的描述符。例如,我们可以为我们的人员对象如下:
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;
}());
使用 Object.defineProperty(( 给出更好地控制我们的属性定义。例如,我们可以指定属性是否正在描述可以动态删除或重新定义,如果其值可以更改,等等上。
我们可以通过设置描述符对象的以下属性来进行此类约束:
- 可写:这是一个布尔值,表示属性可以更改;其默认值为 false
- 可配置:这是一个布尔值,表示属性是否可以更改描述符或删除属性本身;其默认值为 false
- 可枚举:这是一个布尔值,指示该属性是否可以在对象属性的循环中访问;其默认值为假 值
- :这表示与属性关联的值;其默认值未定义
下面是Animal → Dog
继承的简单示例,Animal
有一个getter和一个setter:
//////////////////////////////////////////
// General Animal constructor
function Animal({age, name}) {
// if-statements prevent triggering the setter on initialization
if(name) this.name = name
if(age) this.age = age
}
// an alias "age" must be used, so the setter & getter can use an
// alternative variable, to avoid using "this.age", which will cause
// a stack overflow of "infinite" call stack when setting the value.
Object.defineProperty(Animal.prototype, "age", {
get(){
console.log("Get age:", this.name, this._age) // getting
return this._age
},
set(value){
this._age = value
console.log("Set age:", this.name, this._age) // setting
}
})
//////////////////////////////////////////
// Specific Animal (Dog) constructor
function Dog({age = 0, name = 'dog'}) {
this.name = name
this.age = age
}
// first, defined inheritance
Dog.prototype = new Animal({});
// add whatever additional methods to the prototype of Dog
Object.assign(Dog.prototype, {
bark(woff){
console.log(woff)
}
})
//////////////////////////////////////////
// Instanciating
var koko = new Animal({age:300, name:'koko'})
var dog1 = new Dog({age:1, name:'blacky'})
var dog2 = new Dog({age:5, name:'shorty'})
console.log(dog1)
koko.age
dog1.age = 3;
dog1.age
dog2.age