借用JS中其他对象的函数

时间:2015-11-01 00:05:56

标签: javascript

我有以下代码:

var gameController = {
    scores: [20, 34, 55, 46, 77],
    avgScore: 112,
    players: [
        {name: "Ruth", playerId: 100, age: 22},
        {name: "Shawnee", playerId: 101, age: 21}
    ]
};
var appController = {
    scores: [900, 845, 809, 950],
    avgScore: null,
    avg: function () {
        var sumOfScores = this.scores.reduce(function (prev, cur, index, array) {
            return prev + cur;
        });

        this.avgScore = sumOfScores / this.scores.length;
    }
};
gameController.avgScore = appController.avg();
console.log(gameController.avgScore);

我尝试借用appController中定义的avg方法来为gameController进行计算。我理解在gameController.avgScore = appController.avg();之后,avg方法中的这个关键字仍会指向appController,因为appController会调用avg方法,所以我希望gameController中的avgScore保持不变,但输出是未定义的,为什么?

2 个答案:

答案 0 :(得分:2)

avg不会返回任何内容,因此会隐式返回undefined。你基本上在做gameController.avgScore = undefined;

如果您要将avg方法应用于gameController,可以使用.call

appController.avg.call(gameController);

最好将avg作为独立函数接受数组作为输入(参数)并返回平均值。

答案 1 :(得分:1)

<强>更新 将函数赋值给对象时,在调用函数时将this关键字设置为对象。这仅适用于未绑定的函数引用。如果函数引用绑定到另一个对象,则必须使用Function.bind()方法来确保将其设置为正确的对象。

<强>答案 而不是每次使用调用只是将函数分配给对象。调用该函数时,this设置为对象

gameController.avg = appController.avg; // unbound function reference.
// now when you need to get the average for gameController 
// just call its avg function
gameController.avg();  // this is automatically set to gameControler

最好还是在控制器外部创建功能,并在创建时分配它们。

// define the avg and refer it to the unbound function that you will share
var avg = function () { 
    var sumOfScores = this.scores.reduce(function (prev, cur, index, array) {
        return prev + cur;
    });
    this.avgScore = sumOfScores / this.scores.length;
    console.log(this.avgScore);
}
// create the objects as normal
var gameController = {
    scores: [20, 34, 55, 46, 77],
    avgScore: 112,
    players: [
        {name: "Ruth", playerId: 100, age: 22},
        {name: "Shawnee", playerId: 101, age: 21}
    ],
    avg:avg  // avg is automatically bound to gameController when it is called
};
var appController = {
    scores: [900, 845, 809, 950],
    avgScore: null,
    avg:avg  // avg is automatically bound to appController when it is called
};
// or if you want to get really lazy. 
var otherController = {
    scores: [900, 900, 900, 900],
    avgScore: null,
    avg  // avg is automatically bound to otherController when it is called
         // and it is automatically named avg as well
};
appController.avg();  // 46.4
gameController.avg(); // 876
otherController.avg(); // 900

还有超过六种其他方法可以实现同样的目标。