如何在once()函数中删除未定义的返回(不更改以前的函数)

时间:2018-04-27 21:50:58

标签: javascript callback closures

我有两段代码,它们在add(y)函数的定义上有所不同。一个使用console.log()(原始版本),一个被修改为使用return。第二种方式我可以通过我的提示,这是......

  

编写一个函数,一旦接受回调作为输入并返回一个函数。当第一次调用返回的函数时,它应该调用回调并返回该输出。如果再次调用它,而不是再次调用回调,它将只是从第一次调用时返回输出值。

如何在不修改add(y)的情况下重构第一个代码以实现第二个代码中返回的所需结果?

//Challenge 4
function addByX(x) {
  function add(y) {
    console.log(y + x);
  }
  return add;
}

var addByTwo = addByX(2);

// now call addByTwo with an input of 1
//addByTwo(1);
// now call addByTwo with an input of 2
//addByTwo(5);

//Challenge 5
function once(func) {
  var answer;

  function inner(x) {
    if (!answer) {
      answer = func(x);
      return answer;
    } else {
      return answer;
    }
  }
  return inner;
}

var onceFunc = once(addByTwo);

// UNCOMMENT THESE TO TEST YOUR WORK!
console.log(onceFunc(5)); //should log 7
console.log(onceFunc(10)); //should log 7
console.log(onceFunc(9001)); //should log 7

第二个代码(作品)

//Challenge 4
function addByX(x) {
  function add(y) {
    return y + x;
  }
  return add;
}

var addByTwo = addByX(2);

// now call addByTwo with an input of 1
//addByTwo(1);
// now call addByTwo with an input of 2
//addByTwo(5);

//Challenge 5
function once(func) {
  var answer;

  function inner(x) {
    if (!answer) {
      answer = func(x);
      return answer;
    } else {
      return answer;
    }
  }
  return inner;
}

var onceFunc = once(addByTwo);

// UNCOMMENT THESE TO TEST YOUR WORK!
console.log(onceFunc(5)); //should log 7
console.log(onceFunc(10)); //should log 7
console.log(onceFunc(9001)); //should log 7

2 个答案:

答案 0 :(得分:0)

我们可以使用闭包来捕获函数被调用一次。当true的标志为value时,它已被调用,在这种情况下,它将返回第一次运行该函数时设置的callback。或者,如果这是第一次运行该函数,我们将true设置为value并将cb设置为使用参数str调用的function string_callback(cb) { let called = false, value; return function(str) { if (called) return value; called = true; value = cb(str); return value; } } let my_func = string_callback((input) => input.toUpperCase()); my_func("hihihih"); console.log(my_func("banana")); console.log(my_func("banana")); console.log(my_func("banana"));函数。我们在任何一种情况下都返回此值。

Write a function once that accepts a callback as input and returns a function. When the returned function is called the first time, it should call the callback and return that output. If it is called any additional times, instead of calling the callback
again it will simply return the output value from the first time it was called.
Apr 19, 2018 3:28:39 PM org.postgresql.jdbc.PgConnection <init>
FINE: PostgreSQL JDBC Driver 42.1.4
Apr 19, 2018 3:28:39 PM org.postgresql.jdbc.PgConnection setDefaultFetchSize
FINE:   setDefaultFetchSize = 0
Apr 19, 2018 3:28:39 PM org.postgresql.jdbc.PgConnection setPrepareThreshold
FINE:   setPrepareThreshold = 0
Apr 19, 2018 3:28:39 PM org.postgresql.core.v3.ConnectionFactoryImpl openConnectionImpl
FINE: Trying to establish a protocol version 3 connection to bdlgpmdev01.isus.emc.com:7500
Apr 19, 2018 3:28:39 PM org.postgresql.core.v3.ConnectionFactoryImpl openConnectionImpl
FINE: Receive Buffer Size is 184,640
Apr 19, 2018 3:28:39 PM org.postgresql.core.v3.ConnectionFactoryImpl openConnectionImpl
FINE: Send Buffer Size is 43,520
Apr 19, 2018 3:28:40 PM org.postgresql.jdbc.PgConnection isValid
WARNING: Validating connection.
org.postgresql.util.PSQLException: ERROR: invalid server parameter
    at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2477)
    at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2190)
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:300)
    at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:428)
    at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:354)
    at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:169)
    at org.postgresql.jdbc.PgPreparedStatement.executeUpdate(PgPreparedStatement.java:136)
    at org.postgresql.jdbc.PgConnection.isValid(PgConnection.java:1311)`

答案 1 :(得分:0)

为了扩展@Barmar在他的评论中写的内容,在第一个例子中,你的内部'add'函数没有返回任何东西,因此它的返回值将是未定义的。因此,每次调用“内部”时,答案仍然是假的,因此捕获的“addByTwo”函数将被调用三次。这就是为什么你得到交替数,这是“add”本身记录的加法结果,而undefined是记录的返回值。您可以通过从'add'返回返回值来解决第二个示例中的问题。

现在,我确实想向你指出一些可能有帮助的事情。

1)如果您在第一次调用'onceFunc'时传入-2,则第二个示例仍然会失败。为什么?因为这句话:

if (!answer) {

检查答案是否为假,其中0为(-2 + 2)。您可以通过检查是否未定义答案来解决此问题。

2)我不需要这么灵活,但是通过在捕获的函数上使用'apply'方法,您不必为'inner'指定参数。这意味着您传入的函数可以接受零个,一个或多个参数。

以下是传入-2时代码中断的示例(如第1项中所述):

function addByX(x) {
  function add(y) {
    return y + x;
  }
  return add;
}

var addByTwo = addByX(2);

function once(func) {
  var answer;

  function inner(x) {
    if (!answer) {
      answer = func(x);
      return answer;
    } else {
      return answer;
    }
  }
  return inner;
}

var onceFunc = once(addByTwo);

console.log(onceFunc(-2)); //should log 0
console.log(onceFunc(10)); //should log 0, but it won't

这里修复了处理#1中提到的问题,并提供了#2中提到的灵活性:

function addByX(x) {
  function add(y) {
    return y + x;
  }
  return add;
}

function mult(a, b) {
  return a * b;
}

var addByTwo = addByX(2);

function once(func) {
  var answer;

  function inner() {
    if(typeof answer === 'undefined') {
      answer = func.apply(null, arguments);
      return answer;
    } else {
      return answer;
    }
  }
  return inner;
}

var onceFunc = once(addByTwo);

console.log(onceFunc(-2)); // should log 0
console.log(onceFunc(10)); // should log 0, this time it will
console.log(onceFunc(9001)); // should log 0, and again it will


// this can also be re-used with a function that accepts multiple parameters (or none)
var onceFuncMult = once(mult);

console.log(onceFuncMult(3, 5)); // 15
console.log(onceFuncMult(8, 5)); // still 15

希望这有用,并提供一些额外的信息来帮助您。