为什么这个 JavaScript 函数有效?
Why does this JavaScript function work?
对于模糊的标题深表歉意,但我需要详细说明。这是有问题的代码,我在 http://ariya.ofilabs.com/2013/07/prime-numbers-factorial-and-fibonacci-series-with-javascript-array.html:
上阅读过
function isPrime(i) {
return (i > 1) && Array.apply(0, Array(1 + ~~Math.sqrt(i))).
every(function (x, y) {
console.log(x + ' ' + i % y);
return (y < 2) || (i % y !== 0)
});
}
isPrime(23);
isPrime(19);
isPrime(188);
为了好玩,我添加了这些日志以便我们可以看到一些输出:
undefined NaN
undefined 0
undefined 1
undefined 2
undefined 3
undefined NaN
undefined 0
undefined 1
undefined 1
undefined 3
undefined NaN
undefined 0
undefined 0
这是我第一次看到apply
和every
,所以请耐心等待,但我的理解是apply
基本上调用了Array函数,其中第一个参数是它的 this
的替代,第二个是输出...从没想过这会有用,但这个函数似乎有效,所以...
在这里,他们似乎正在创建一个长度等于所讨论数字的平方根的数组。我想这是有道理的,因为平方根是所讨论数字的最大可能因数。
好的,所以从这里开始,如果我们要记录第一个数字的数组,它看起来像这样:
> var i = 23;
undefined
> Array.apply(0, Array(1 + ~~Math.sqrt(i)));
[ undefined, undefined, undefined, undefined, undefined ]
太好了,这是一个包含五个 undefined
的数组。好的,好的,所以从这里开始,every
方法应该检查该数组中的每个元素是否通过回调函数测试(或其他)。
Microsoft 文档为 every
方法指定了三个可能的参数:
- 值
- 指数
- 数组
因此,在这个例子中x
是值,即undefined
,y
是索引。
我们的输出与该结论一致。但是,我仍然对嵌套的 return 语句感到模糊(如果最低的 returns,它的 parent 也 return 吗?), ||
运算符在这里(如果第一个测试通过,每个循环都会停止吗?),以及它通常是如何工作的。
编辑
日志应该带有 x,而不是 y。我的错误:
console.log(y + ' ' + i % y); -> console.log(x + ' ' + i % y);
说明
所以,你问我是怎么找到这段代码的?嗯,当然,检查 Java 中素数的最简单方法是这样的:
public static boolean isPrime(double num) {
for (double i = 2.0; i < sqrt(num); i++) {
if (num % i == 0.0) {
return true;
}
}
return false;
}
或Python
def isPrime(num):
x = 2
isPrime = True
while x < math.sqrt(num):
if num % x == 0:
isPrime = False
break
x = x + 1
return isPrime
或js
function isPrime(n) {
for (var i = 2.0; i < Math.sqrt(n); i++) {
if (n % i === 0.0) {
return false;
}
}
return true;
}
但是假设我想检查一个数字的最大质因数,例如 600851475143
这些循环方法会花费太长时间,对吧?我认为这个 "hack",正如我们描述的那样,可能效率更低,因为它使用数组而不是整数或浮点数,但即便如此,我只是在寻找一种更有效的方法来解决这个问题。
post 中的代码基本上是废话。教人们写代码的同时使用 hack 是垃圾。是的,黑客有他们的位置(优化),但教育工作者应该展示不依赖于他们的解决方案。
技巧 1
// the 0 isn't even relevant here. it should be null
Array.apply(0, Array(1 + ...))
技巧 2
// This is just Math.floor(x), but trying to be clever
~~x
技巧 3
// this is an outright sin; totally unreadable code
// I bet most people don't know the binding precedence of % over +
y + ' ' + i % y
// this is evaluated as
y + ' ' + (i % y)
// example
2 + ' ' + (5 % 2) //=> "2 1"
I'm still fuzzy about nested return statements (if the lowest one returns, does its parent also return?),
没有。一个return
只有return语句存在的函数
the || operator here (if the first test passes, does the every loop stop?)
没有。一旦回调 return 成为 false
,Array.prototype.every
将 return false
。如果 false
从未从回调中 return 编辑,.every
将 return `true.
function isEven(x) { return x % 2 === 0; }
[2,4,5,6].every(isEven); //=> false, stops at the 5
[2,4,6].every(isEven); //=> true
这里有一个.every
短路的例子
[1,2,3,4,5,6].every(x=> {console.log(x, x<4); return x<4;});
// 1 true
// 2 true
// 3 true
// 4 false
//=> false
看看它是如何在回调 returns false
后停止的?甚至没有计算元素 5
和 6
。
... and just generally how this works.
&&
类似于 Array.prototype.every
和 ||
类似于 Array.prototype.some
.
&&
将在遇到第一个 false
时立即 return false
;换句话说,它期望 每个 参数是 true
.
||
将在遇到第一个 true
时立即 return true
;换句话说,它只希望 some 参数为 true
.
对于模糊的标题深表歉意,但我需要详细说明。这是有问题的代码,我在 http://ariya.ofilabs.com/2013/07/prime-numbers-factorial-and-fibonacci-series-with-javascript-array.html:
上阅读过function isPrime(i) {
return (i > 1) && Array.apply(0, Array(1 + ~~Math.sqrt(i))).
every(function (x, y) {
console.log(x + ' ' + i % y);
return (y < 2) || (i % y !== 0)
});
}
isPrime(23);
isPrime(19);
isPrime(188);
为了好玩,我添加了这些日志以便我们可以看到一些输出:
undefined NaN
undefined 0
undefined 1
undefined 2
undefined 3
undefined NaN
undefined 0
undefined 1
undefined 1
undefined 3
undefined NaN
undefined 0
undefined 0
这是我第一次看到apply
和every
,所以请耐心等待,但我的理解是apply
基本上调用了Array函数,其中第一个参数是它的 this
的替代,第二个是输出...从没想过这会有用,但这个函数似乎有效,所以...
在这里,他们似乎正在创建一个长度等于所讨论数字的平方根的数组。我想这是有道理的,因为平方根是所讨论数字的最大可能因数。
好的,所以从这里开始,如果我们要记录第一个数字的数组,它看起来像这样:
> var i = 23;
undefined
> Array.apply(0, Array(1 + ~~Math.sqrt(i)));
[ undefined, undefined, undefined, undefined, undefined ]
太好了,这是一个包含五个 undefined
的数组。好的,好的,所以从这里开始,every
方法应该检查该数组中的每个元素是否通过回调函数测试(或其他)。
Microsoft 文档为 every
方法指定了三个可能的参数:
- 值
- 指数
- 数组
因此,在这个例子中x
是值,即undefined
,y
是索引。
我们的输出与该结论一致。但是,我仍然对嵌套的 return 语句感到模糊(如果最低的 returns,它的 parent 也 return 吗?), ||
运算符在这里(如果第一个测试通过,每个循环都会停止吗?),以及它通常是如何工作的。
编辑
日志应该带有 x,而不是 y。我的错误:
console.log(y + ' ' + i % y); -> console.log(x + ' ' + i % y);
说明
所以,你问我是怎么找到这段代码的?嗯,当然,检查 Java 中素数的最简单方法是这样的:
public static boolean isPrime(double num) {
for (double i = 2.0; i < sqrt(num); i++) {
if (num % i == 0.0) {
return true;
}
}
return false;
}
或Python
def isPrime(num):
x = 2
isPrime = True
while x < math.sqrt(num):
if num % x == 0:
isPrime = False
break
x = x + 1
return isPrime
或js
function isPrime(n) {
for (var i = 2.0; i < Math.sqrt(n); i++) {
if (n % i === 0.0) {
return false;
}
}
return true;
}
但是假设我想检查一个数字的最大质因数,例如 600851475143
这些循环方法会花费太长时间,对吧?我认为这个 "hack",正如我们描述的那样,可能效率更低,因为它使用数组而不是整数或浮点数,但即便如此,我只是在寻找一种更有效的方法来解决这个问题。
post 中的代码基本上是废话。教人们写代码的同时使用 hack 是垃圾。是的,黑客有他们的位置(优化),但教育工作者应该展示不依赖于他们的解决方案。
技巧 1
// the 0 isn't even relevant here. it should be null
Array.apply(0, Array(1 + ...))
技巧 2
// This is just Math.floor(x), but trying to be clever
~~x
技巧 3
// this is an outright sin; totally unreadable code
// I bet most people don't know the binding precedence of % over +
y + ' ' + i % y
// this is evaluated as
y + ' ' + (i % y)
// example
2 + ' ' + (5 % 2) //=> "2 1"
I'm still fuzzy about nested return statements (if the lowest one returns, does its parent also return?),
没有。一个return
只有return语句存在的函数
the || operator here (if the first test passes, does the every loop stop?)
没有。一旦回调 return 成为 false
,Array.prototype.every
将 return false
。如果 false
从未从回调中 return 编辑,.every
将 return `true.
function isEven(x) { return x % 2 === 0; }
[2,4,5,6].every(isEven); //=> false, stops at the 5
[2,4,6].every(isEven); //=> true
这里有一个.every
短路的例子
[1,2,3,4,5,6].every(x=> {console.log(x, x<4); return x<4;});
// 1 true
// 2 true
// 3 true
// 4 false
//=> false
看看它是如何在回调 returns false
后停止的?甚至没有计算元素 5
和 6
。
... and just generally how this works.
&&
类似于 Array.prototype.every
和 ||
类似于 Array.prototype.some
.
&&
将在遇到第一个 false
时立即 return false
;换句话说,它期望 每个 参数是 true
.
||
将在遇到第一个 true
时立即 return true
;换句话说,它只希望 some 参数为 true
.