Javascript 如何将构造函数对象值设置为其他值的函数?

Javascript 如何将构造函数对象值设置为其他值的函数?,javascript,Javascript,我试图通过在对象构造函数中的两个其他属性上运行函数来生成对象属性 当我运行以下代码时: var ConstObj = function() { this.compositionDict = { "rock": 0.8, "iron": 0.15, "gold": 0.05 }; this.totalVolume = 10000; this.compVolDict = Object.keys(this.composit

我试图通过在对象构造函数中的两个其他属性上运行函数来生成对象属性

当我运行以下代码时:

var ConstObj = function() {
    this.compositionDict = {
        "rock": 0.8,
        "iron": 0.15,
        "gold": 0.05
    };
    this.totalVolume = 10000;
    this.compVolDict = Object.keys(this.compositionDict).reduce(function(prev, curr) {
        prev[curr] = this.compositionDict[curr] * this.totalVol;
        return prev;
    }, {});
}
var tempObj = new ConstObj;
我得到以下错误:

Uncaught TypeError:无法读取未定义(…)的属性“rock”
我认为这是行不通的,因为在函数运行时,对象属性实际上没有定义——但我不知道我要做什么有什么好的解决方法


我可以创建一个在创建对象后添加新属性的函数,但这类事情似乎应该会起作用。

这是因为
这个
reduce
函数中不是正确的值。无论何时创建新闭包,例如
function(){…}
,都会创建一个新的上下文。为了使
指向正确的上下文,您必须
绑定该函数,或者必须使用变量引用原始上下文

this.compVolDict = Object.keys(this.compositionDict).reduce(function(prev, curr) {
    prev[curr] = this.compositionDict[curr] * this.totalVol;
    return prev;
}.bind(this), {});
或者可以使用变量记录要在函数内部使用的上下文。这有点难看,但你会在各种各样的用户区脚本中看到这种情况

var _this = this;
this.compVolDict = Object.keys(this.compositionDict).reduce(function(prev, curr) {
    prev[curr] = _this.compositionDict[curr] * _this.totalVol;
    return prev;
}, {});
最后,另一个解决方案是使用一个。显然,这是最优雅的解决方案

this.compVolDict = Object.keys(this.compositionDict).reduce((prev, curr) => {
    prev[curr] = this.compositionDict[curr] * this.totalVol;
    return prev;
}, {});

如果您不能使用ES6,您可以使用将ES6转换为ES5的transpiler。这是一个很好的方法,可以开始利用新的ES6功能,但仍然能够在ES5环境中运行它们。

这一点。compositionDict
在您的
reduce
中是
未定义的,因为您在不同的范围内。
(即
函数(prev,curr){

保存对
ConstObj
函数作用域的引用,然后改用该引用:

var ConstObj = function() {
    var that = this; // Store the reference to `this`.
    this.compositionDict = {
        "rock": 0.8,
        "iron": 0.15,
        "gold": 0.05
    };
    this.totalVolume = 10000;
    this.compVolDict = Object.keys(this.compositionDict).reduce(function(prev, curr) {
        prev[curr] = that.compositionDict[curr] * that.totalVol;
        return prev; // ^ use `that` instead of `this`
    }, {});
}

是的,没关系。这就是为什么我首先提供了两个现成的解决方案,最后提供了一个他/她可能不知道的解决方案。用户可能甚至不知道ES6有一个功能可以解决他/她的问题。请记住,目前对ES6的浏览器支持最好。我不是说你应该忘记ES6,不过,它只需要一些时间。谢谢为了获得全面的答案,我将对
bind
@Cerbrus和Transpiler做更多的研究,就像您现在就可以开始使用ES6一样;即使是在还不支持ES6的环境中。