只是想分享一些小技巧,我学会了将变量传递到JS Array.forEach()方法的范围内。
我遇到了需要使用forEach循环来构建数据集的情况。但是我还需要访问当前作用域中的变量(我需要能够在循环中引用this
)。
这是我当时的情况:
var dataset = {
data: [],
backgroundColor:[],
};
items.forEach(function (item) {
dataset.data.push(item.age);
if (item.age < 2) {
dataset.bgColor.push(this.green);
} else if (item.age < 5) {
dataset.bgColor.push(this.yellow);
} else {
dataset.bgColor.push(this.red);
}
}, this);
this.refreshGraph(dataset);
无法从循环内访问数据集。那么我们如何在迭代时访问它?
我没有在堆栈溢出时看到此解决方案,它不适合我能找到的任何问题。
下面的答案:
具有es6的能力如果使用箭头功能,this将来自
items.forEach(item => {
// You can use this as out of the forEach scope
});
箭头功能本身没有此功能。这个值使用封闭的词汇范围;箭头功能遵循正常可变查找规则。所以在寻找这个不是当前范围内的箭头功能最终会找到从其随附的范围。
另一个很好的解释:https://hackernoon.com/javascript-es6-arrow-functions-and-lexical-this-f2a3e2a5e8c4
如果您的某个函数超出某些数据范围,但需要访问它,则可以使用将该数据集作为第一个参数的咖喱函数,并且仍然可以在整个过程中正常使用this
:
//curried function that uses `dataset` and `this` but it is not
//in the context where the iteration happens
function makeLoopCallback(dataset) {
return function(item) {
dataset.data.push(item.age);
if (item.age < 2) {
dataset.bgColor.push(this.green);
} else if (item.age < 5) {
dataset.bgColor.push(this.yellow);
} else {
dataset.bgColor.push(this.red);
}
}
}
//object to serve as `this` context for a function
var obj = {
green: "Green",
yellow: "Yellow",
red: "Red",
doSomething: function(items) {
var data = {
data: [],
bgColor:[],
};
items.forEach(makeLoopCallback(data), this);
return data;
}
}
//set up some dummy data
var input = [ { age: 1 }, { age: 2 }, { age: 3 }, { age: 4 }, { age: 5 }, { age: 6 } ];
//call the function
console.log(obj.doSomething(input))
另一种选择是将Array#reduce
而不是Array#reduce
与直接使用两个参数的函数一起使用。由于Array#forEach
无法设置Array#forEach
上下文,因此您可以使用.reduce
来做到这一点:
this
解决方案是将JSON对象作为Function#bind
参数传递。
因此,在我们拥有之前:
Function#bind
现在我们有:
//external function that uses `dataset` and `this` but it is not
//in the context where the iteration happens
function external(dataset, item) {
dataset.data.push(item.age);
if (item.age < 2) {
dataset.bgColor.push(this.green);
} else if (item.age < 5) {
dataset.bgColor.push(this.yellow);
} else {
dataset.bgColor.push(this.red);
}
return dataset;
}
//object to serve as `this` context for a function
var obj = {
green: "Green",
yellow: "Yellow",
red: "Red",
doSomething: function(items) {
var data = {
data: [],
bgColor:[],
};
return items.reduce(external.bind(this), data);
}
}
//set up some dummy data
var input = [ { age: 1 }, { age: 2 }, { age: 3 }, { age: 4 }, { age: 5 }, { age: 6 } ];
//call the function
console.log(obj.doSomething(input))
现在您可以在使用匿名函数进行迭代时更改数据:)
完整示例:
this
Array.prototype.forEach(callbackFun,?this)
您可以将Array.forEach(function(){}, this)
// "this" is just an object ^^^^ just like anything else in JavaScript
作为此参数传递给Array.forEach(function(){}, {_self: this, dataset: dataset})
// you can access _self and dataset just as if they were in scope
var dataset = {
data: [],
backgroundColor:[],
};
items.forEach(function (item) {
dataset.data.push(item.age);
if (item.age < 2) {
dataset.bgColor.push(_self.green);
} else if (item.age < 5) {
dataset.bgColor.push(_self.yellow);
} else {
dataset.bgColor.push(_self.red);
}
}, { _self: this , dataset: dataset});