简体   繁体   English

JavaScript编码挑战

[英]Javascript coding challenge

I was given this question by a prospective client to solve and I wasn't able to on time, only the makeSFns function can be altered and as I was altering to give specific square values to match the square function (based on position in arr ) I kept getting the error of funcs[i] is not a function which is weird because the square function its being compared to is returning a number , how does something that's expecting a function match a number? 准客户向我提出了这个问题,我无法按时解决,只能更改makeSFns函数,并且由于要更改以提供特定的平方值以匹配square函数(基于arr位置)我不断收到funcs[i] is not a function的错误,这funcs[i] is not a function很奇怪funcs[i] is not a function ,因为与之相比的平方函数正在返回一个number ,期望该函数与数字匹配的东西如何?

 //Task: fix makeSFns function to show correct answer var arr = [ Math.random(), Math.random(), Math.random(), Math.random() ]; var square = function (x) { return x * x; }; function makeSFns(arr, square) { var fns = []; for (var i = 0; i < arr.length; i++) { fns.push(function() { return square(arr[i]); }); } return fns; } var funcs = makeSFns(arr, square); isEqual = true; for (var i = 0; i < arr.length; i++) { if (funcs[i]() !== square(arr[i])) { isEqual = false; console.log('wrong answer'); break; } } if (isEqual) console.log('correct answer'); 

Some asking how I got the error, I tried finding a way to get position in arr and then returning 有人问我是怎么得到错误的,我试图找到一种方法来获得arr位置,然后返回

var position = 0; //outside the function

for (var i = 0; i < arr.length; i++) {
    return square(arr[i]);             //replacing the push function
    position + 1; 
 }

you are passing arr[i] into square function inside makeSFns but this value lost as it is not a true closure. 您正在将arr [i]传递到makeSFns内的平方函数中,但是该值丢失了,因为它不是真正的闭包。

 //Task: fix makeSFns function to show correct answer var arr = [ Math.random(), Math.random(), Math.random(), Math.random() ]; var square = function (x) { return x * x; }; function makeSFns(arr, square) { return arr.map((num, i)=>()=>{ return square(arr[i]) }); } var funcs = makeSFns(arr, square); isEqual = true; for (var i = 0; i < arr.length; i++) { if (funcs[i]() !== square(arr[i])) { isEqual = false; console.log('wrong answer'); break; } } if (isEqual) console.log('correct answer'); 

It is a classic, since the push function is called after the loop, it's referencing the last known i , it is not correctly captured. 这是经典方法,因为在循环之后调用了push函数,所以它引用的是最后一个已知的i ,因此无法正确捕获。

 //Task: fix makeSFns function to show correct answer var arr = [ Math.random(), Math.random(), Math.random(), Math.random() ]; var square = function (x) { return x * x; }; function makeSFns(arr, square) { var fns = []; for (var i = 0; i < arr.length; i++) { (function(n) { fns.push(function() { return square(arr[n]); }); })(i); } return fns; } var funcs = makeSFns(arr, square); isEqual = true; for (var i = 0; i < arr.length; i++) { if (funcs[i]() !== square(arr[i])) { isEqual = false; alert('wrong answer'); break; } } if (isEqual) alert('correct answer'); 

More on the subject: 有关此主题的更多信息:

Edit: an interesting tranformation done by TypeScript when using the let keyword : 编辑: 使用let关键字时,TypeScript完成了一个有趣的转换

TS TS

for (let i = 0; i < arr.length; i++) {
    fns.push(function() {
        return square(arr[i]);
    });
}

JS JS

var _loop_1 = function (i) {
    fns.push(function () {
        return square(arr[i]);
    });
};
for (var i = 0; i < arr.length; i++) {
    _loop_1(i);
}

It is because the array's reference is not available to the function being pushed into fns array, a classic javascript scenario. 这是因为数组的引用不适用于将函数推入fns数组的功能,这是经典的JavaScript场景。

 //Task: fix makeSFns function to show correct answer //Task: fix makeSFns function to show correct answer var arr = [ Math.random(), Math.random(), Math.random(), Math.random() ]; var square = function (x) { return x * x; }; function makeSFns(arr, square) { var fns = []; for (var i = 0; i < arr.length; i++) { let myFn = function(myInput) { return square(myInput); }; fns.push(myFn.bind(null,arr[i])); } return fns; } var funcs = makeSFns(arr, square); isEqual = true; for (var i = 0; i < arr.length; i++) { if (funcs[i]() !== square(arr[i])) { isEqual = false; console.log('wrong answer'); break; } } if (isEqual) console.log('correct answer'); 

There's a solution to this that requires changing one keyword only: 有一个解决方案,只需更改一个关键字即可:

  function makeSFns(arr, square) {
    var fns = [];
-    for (var i = 0; i < arr.length; i++) {
+    for (let i = 0; i < arr.length; i++) {
       fns.push(function() {
         return square(arr[i]);
       });
     }
    return fns;
  }

Using let changes the scope of i and makes it behave like a separate closure. 使用let更改i的范围,并使它的行为类似于单独的闭包。 Each iteration in the for loop will have it's own instance of i . for循环中的每个迭代都将拥有自己的i实例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM