为什么这个JavaScript函数有效?

时间:2016-05-25 23:41:00

标签: javascript arrays functional-programming numbers primes

对于模糊的标题很多道歉,但我需要详细说明。以下是我在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

这是我第一次见到applyevery,所以请耐心等待,但我的理解是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是值,即undefinedy是索引。

我们的结果同意这一结论。但是,我对嵌套的返回语句仍然很模糊(如果最低的返回语句,它的父语句也返回吗?),这里的||运算符(如果第一个测试通过,那么每个循环都会停止吗?) ,一般来说这是如何工作的。

修改

日志应该是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这样的数字的最大素数因子这些循环方法需要太长时间,对吗?我认为这&#34; hack&#34;正如我们所描述的那样,可能效率更低,因为它使用数组而不是整数或浮点数,但即使如此,我只是在寻找一种更有效的解决方法那个问题。

1 个答案:

答案 0 :(得分:4)

该帖子中的代码基本上是废话。教人们在使用黑客同时编写代码是垃圾。是的,黑客有自己的位置(优化),但教育工作者应该展示不依赖于它们的解决方案。

Hack 1

// the 0 isn't even relevant here. it should be null
Array.apply(0, Array(1 + ...))

Hack 2

// This is just Math.floor(x), but trying to be clever  
~~x

Hack 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"
  

我对嵌套的返回语句仍然很模糊(如果最低的返回语句,它的父语句也会返回吗?),

没有。 return仅返回

中语句存在的函数
  

||这里的运算符(如果第一个测试通过,那么每个循环都会停止吗?)

没有。一旦回调返回Array.prototype.everyfalse将返回false。如果永远不会从回调中返回false.every将返回“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

一旦回调返回false,看看它是如何停止的?元素56甚至无法评估。

  

......而且一般来说这是如何运作的。

&&类似Array.prototype.every||之类的作品类似于Array.prototype.some

遇到第一个&&后,

false将返回false;换句话说,它希望 每个 参数都为true

遇到第一个||后,

true将返回true;换句话说,它只希望 某些 参数为true

相关:short circuit evaluation