21

这可能是我错过的一些非常愚蠢的事情,但是我如何让一个类的属性根据同一个类中其他属性的值自动重新计算?

例如

function Test() {
    this.prop1 = 1;
    this.prop2 = 2;
    this.prop3 = this.prop1 + this.prop2;

}

tester = new Test();

alert (tester.prop1); // expect 1
alert (tester.prop2); // expect 2
alert (tester.prop3); // expect 3

tester.prop1 += 1;

alert (tester.prop1); // expect 2
alert (tester.prop2); // expect 2
alert (tester.prop3); // expect 4

还是我需要将 prop3 设置为 = calcProp3() 然后包含如下函数:

this.calcProp3 = function() {
        var calc = this.prop1 + this.prop2;
        return calc;
    }

谢谢大家。

4

3 回答 3

26

还是我需要将 prop3 设置为 = calcProp3() 然后包含一个函数

你有两个选择:

  1. 创建一个带有getter的属性,当你使用它时,它看起来像一个简单的属性访问,但实际上是在调用一个函数,或者

  2. 执行您的calcProp3功能,这使编码人员可以清楚地Test知道他们正在调用一个功能

如果您需要支持像 IE8 这样真正过时的浏览器,选项 2 是您唯一的选择,因为 IE8 不支持 getter。

使用吸气剂

在 2017 年,您可能会在 a 中定义它class(如果需要,为不支持 ES2015 的 [aka "ES6"] 的浏览器进行转换class):

class Test {
  constructor() {
    this.prop1 = 1;
    this.prop2 = 2;
  }
  get prop3() {
    return this.prop1 + this.prop2;
  }
}
const t = new Test();
console.log(t.prop3); // 3
t.prop1 = 2;
console.log(t.prop3); // 4

如果您想限制自己使用 ES5 的功能(规范于 2009 年 12 月发布,IE8 不支持),您Test.prototype可以使用Object.defineProperty规范MDN)定义一个 getter:

function Test() {
  this.prop1 = 1;
  this.prop2 = 2;
}
Object.defineProperty(Test.prototype, "prop3", {
  get: function() {
    return this.prop1 + this.prop2;
  }
});
var t = new Test();
console.log(t.prop3); // 3
t.prop1 = 2;
console.log(t.prop3); // 4

...或者通过替换Test.prototype和使用 getter 的对象初始化器语法(记住 set constructor):

function Test() {
  this.prop1 = 1;
  this.prop2 = 2;
}
Test.prototype = {
  constructor: Test,
  get prop3() {
    return this.prop1 + this.prop2;
  }
};
var t = new Test();
console.log(t.prop3); // 3
t.prop1 = 2;
console.log(t.prop3); // 4

使用函数

在 2017 年,您可能会将其定义为使用class语法的方法(如果需要,对旧浏览器进行转译):

class Test {
  constructor() {
    this.prop1 = 1;
    this.prop2 = 2;
  }
  calcProp3() {
    return this.prop1 + this.prop2;
  }
}
const t = new Test();
console.log(t.calcProp3()); // 3
t.prop1 = 2;
console.log(t.calcProp3()); // 4

如果你想坚持使用 ES5(在这种情况下实际上是 ES3)特性来支持过时的浏览器,只需在原型中添加一个函数:

function Test() {
  this.prop1 = 1;
  this.prop2 = 2;
}
Test.prototype.calcProp3 = function calcProp3() {
  return this.prop1 + this.prop2;
};
var t = new Test();
console.log(t.calcProp3()); // 3
t.prop1 = 2;
console.log(t.calcProp3()); // 4

于 2012-04-23T14:38:29.927 回答
3

Javascript 现在支持通过Object.defineProperties().

function Test() {
    this.prop1 = 1;
    this.prop2 = 2;
}
Object.defineProperties(Test.prototype, {
    prop3: {
        get: function test_prop3_get(){ return this.prop1 + this.prop2 },
    },
});

tester = new Test();

alert (tester.prop1); //=> 1
alert (tester.prop2); //=> 2
alert (tester.prop3); //=> 3

tester.prop1 += 1;

alert (tester.prop1); //=> 2
alert (tester.prop2); //=> 2
alert (tester.prop3); //=> 4
于 2014-08-01T23:47:19.883 回答
1

在 ES6 之后你可以在构造函数中计算:

class Test {
  constructor() {
    this.prop1 = 1;
    this.prop2 = 2;
    this.suma = this.prop1 + this.prop2;
  }
  get prop3() {
    return this.suma;
  }
}
const t = new Test();
console.log(t.suma);
console.log(t.prop3); // 3

于 2017-09-23T17:16:33.227 回答