Javascript 使用函数优于循环有什么好处?
函数迭代器似乎正在取代JS中for循环的使用 与for/while循环相比,传递诸如Javascript 使用函数优于循环有什么好处?,javascript,loops,closures,Javascript,Loops,Closures,函数迭代器似乎正在取代JS中for循环的使用 与for/while循环相比,传递诸如map或reduce之类的函数有什么好处 var numbers = [1, 4, 9]; var doubles = numbers.map(function(num) { return num * 2; }); var doubles = []; for (i = 0; i < numbers.length; i++) { doubles[i] = numbers[i] * 2; }
map
或reduce
之类的函数有什么好处
var numbers = [1, 4, 9];
var doubles = numbers.map(function(num) {
return num * 2;
});
var doubles = [];
for (i = 0; i < numbers.length; i++) {
doubles[i] = numbers[i] * 2;
}
var编号=[1,4,9];
var doubles=numbers.map(函数(num){
返回数*2;
});
var Double=[];
对于(i=0;i
这是一个范式转变。后者是命令式编程的一种形式,用户创建计算机使用的数据。前者本质上是一种更基于函数的方法,源于数学,利用已有的数据(代码)
两者在理论(处理)上没有优势,尽管应用于计算机的当前状态,函数式编程随着处理能力的提高变得更加有用
函数式编程允许一种基于数学的推理形式,强调输入和输出。JavaScript尤其擅长处理这种风格,因为函数是一流的数据类型我不知道为什么您会将
map
的使用称为“闭包”。闭包完全是另一回事map
是一个高阶函数——定义为对函数进行操作(获取或返回)的函数。这种编程风格可以粗略地称为“函数式”
使用像map
这样的函数有优点也有缺点。正如一位评论者所指出的,它更加紧凑:
function sum(array) {
var sum = 0;
for (var i = 0; i < array.length; i++) sum += array[i];
return sum;
}
其中add
是函数add(a,b){返回a+b;}
更紧凑意味着可读性更强,bug的表面积更小。名为add
的函数的使用也提高了可读性;我们可以很容易地直觉地知道,操作是添加数组的元素
基本上,所有数组函数都具有for循环等价物,这需要设置更多变量和编写更多逻辑。例如,map
function map(array, fn) {
var result = [];
for (var i = 0; i < array.length; i++) result.push(fn(array[i]));
return result;
}
现在我们将每个元素加倍:
function double(array) {
var result = [];
for (var i = 0; i < array.length; i++) result.push(array[i] * 2);
return result;
}
仅对位于1000000位置的单个元素执行操作,并根据需要返回稀疏数组
功能性风格也为灵活性提供了更多的可能性。假设我们想推广乘法的概念。我可以编写一个高阶函数来创建一个函数,该函数将某个值乘以某个特定因子:
function multiply(n) {
return function(x) {
return n * x;
};
}
现在我可以写作了
array.map(multiply(2))
在for-loop解决方案中很难实现这种简洁性和表达性
forEach
和map
等可能比for循环慢。如果您的代码在一个紧循环中运行了一百万次,那么这可能是一个问题。在现实世界中,这很少是一个问题。最好优先考虑代码的可读性和紧凑性
但是,没有人强迫您使用map
或filter
。在ES7或其他任何调用中,您将能够使用数组理解以更可读的方式完成相同的任务:
[ for (i of array) if (i % 2) i + 1 ]
它结合了过滤器和贴图
再远一点,如果您计划编写一个遍历数组的生成器,并从每个元素产生一些计算,那么您需要使用for循环,因为在forEach
回调中无法产生:
function *double(array) {
for (var i = 0; i < array.length; i++) yield array[i]*2;
}
function *double(array) {
array.forEach(elt => yield elt*2); // DOESN'T WORK!!
}
函数*double(数组){
对于(var i=0;iyielt*2);//不起作用!!
}
这里已经有了很好的答案。随着时间的推移,我只想补充一件事:当你用“命令式”/“旧的方式”做事时,它倾向于鼓励一种带有大量中间变量的编程风格,到处都是可变的东西,还有“当我在迭代时,我还可以在相同的数据上做另一件事”这是代码设计中最大的陷阱——牺牲关注点的分离来获得可疑的性能增益。考虑这个例子
const numbers = [1,4,9,16];
let sum = 0;
let onlyEvenNumbers = [];
for(i = 0; i < numbers.length; i++) {
sum += numbers[i];
if(numbers[i] % 2 == 0) {
onlyEvenNumbers.push(numbers[i]);
}
}
嗯,这不是结束,而是方法的作用
map
和reduce
对数组执行特定操作,它们不仅仅像for
循环那样迭代?简洁性(使用es6中的arrow funcs会更好),如果您不喜欢它们,您不必使用它们,大多数事情都可以在没有新的(ish)的情况下完成数组方法。此处传递给.map()
的匿名回调形成的闭包基本上与任何代码的工作方式无关。函数本身当然有,但调用形成的闭包却没有……这是一个清晰的声音。几年来我几乎只做js,最近我做了一些php,我受不了回到“旧方式”
[ for (i of array) if (i % 2) i + 1 ]
function *double(array) {
for (var i = 0; i < array.length; i++) yield array[i]*2;
}
function *double(array) {
array.forEach(elt => yield elt*2); // DOESN'T WORK!!
}
const numbers = [1,4,9,16];
let sum = 0;
let onlyEvenNumbers = [];
for(i = 0; i < numbers.length; i++) {
sum += numbers[i];
if(numbers[i] % 2 == 0) {
onlyEvenNumbers.push(numbers[i]);
}
}
const numbers = [1,4,9,16];
const sum = numbers.reduce((acc, val) => acc + val);
const onlyEvenNumbers = numbers.filter(num => num % 2 == 0);