Javascript设计一个函数,在return和callback都可以实现的前提下,用return还是callback?

return方式:

function getState(obj){
  var result = {
      //获取obj的某些属性
  }
 return result;
}

callback方式:

function getSate(obj,callback){
   var result = {
      //获取obj的某些属性
   }
   callback&&callback(result);
}

第一种我可以通过这种方式来拿到state然后处理:

var result = getState(obj);

第二种我可以通过回调函数:

getState(obj,function(result){
    //处理result
})

有时候两种方式均可以达到目的,那么这个时候该把这个函数设计为return方式还是callback方式呢?
二者是否有效率上的区别?或者在设计一个函数的时候,哪些特定的场景该用特定哪一个方式呢?
谢谢。

阅读 11.8k
10 个回答

看你的使用场景
1.如果你的函数中执行的操作是异步的,那么需要传入其它函数作为异步执行结果的回调函数

   function getSome(doneCallback){
    $.ajax({
        
        success: doneCallback
    });  
   }

2.如果你的函数是同步执行函数,需要其它外部函数的辅助完成功能,那就传入函数作为辅助函数使用

var array=[....];
array.sort(function(a,b){
    ....
});

3.如果你的函数是同步执行函数,不依赖其它函数就可以完成功能的话,那么直接返回结果就好
4.当然即使你的函数式同步执行的,也可以传入函数,作为函数执行结果的传递通道,但是这个用法会让人误以为是异步执行的

function calc(i,resultCallback){
    resultCallback();
}

不用那么纠结,接口清晰明了就好~~~

纠正一下问题,你列举的两种情况不是同步和异步的区别,而是非回调和回调的区别。异步是指不用等这段代码结束后面的代码就已经在进行了,从代码上来看你的代码都是线形执行的,断然是升级不到异步的档次了。

回调与非回调就看你是否要自定义回调函数,如果不需要自定义回调函数,谁喜欢每次运行函数的时候还拖个小尾巴。

像你题目中的情况,直接return就好了。
回调通常用在异步情况下或者像Array.prototype.forEach那样为你屏蔽迭代的情况下。

其实两种情况对于效率来说都是微乎其微的,主要还是看使用的场景和上下文

个人在设计通用模块函数的时候会考虑到两种情况,比如在 Node 的场景下,配合 async 进行流控制的时候,使用 callback 会比较舒服,而有时候需要直接返回值进行操作。这时候我会把两种方式都写入一个函数,举个栗子:

const _ = require('lodash');

function handleSomething(arg1, arg2, cb) {
    cb = _.isFunction(cb) ? cb : _.noop;
    
    var result = arg1 + arg2;
    
    cb(null, result);
    
    return result;
}

直接返回promise啦,上来就是链式的。回调都是邪教……

比如说ajax,以前都是

$.ajax({
    success: function() { /* do some thing... 一大堆接下来的逻辑 */ }
});

现在就是


    $.ajax().then(function(){
        // do some thing...
    }).then(function() {
        // do some thing...
    }).then(function() {
        // do some thing...
    })
新手上路,请多包涵

回调用于处理未来不确定时刻函数的返回结果。

js的流程控制这几年发展了不少,callback是最早的流程控制方式,最新的es6里加入了promise、yield、generator特性。建议楼主了解一下。

可以尝试用TDD解决哦,先写个单元测试,看一下哪个方案更易于测试,更易于维护

我都是cb&&cb()然后再return想用啥用啥。

看过几种常见的方式:

  • 返回成功失败,结果实参传递

StringWriter writer = new StringWriter();
VelocityEngine engine = new VelocityEngine();

if (engine.evaluate(new VelocityContext(data), writer, "", content)) {
    return writer.toString();
}
  • 通过指针

IContext *pContext = NULL; 
rs = ExecuteCommand(handle, &pContext);
if (SUCCEEDED(rs)) {
    pContext->Release();
}
  • 通过回调函数

function loadPage(callback) {
    jQuery.ajax('url', {
        method: 'post',
        dataType: 'json',
        success: function(result) {
            callback(0, result);
        },
        error: function(result) {
            callback(500, result)
        }
    });
}
  • 个人常用的方式

function validForm(form, opt) {
    var element = form.elements;
    var hasError = 0;
    for (var i = 0; i < element.length; i++) {
        if (!validItem(element[i])) {
            hasError = 1;
            error.push(getLastError());
        }
    }
    opt.success = !hasError;
    return hasError;
}


var context = {
    success: 1,
    error: []
};

if(!validForm(form, context)) {
    showError(context.error);
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题