在js中,经常会遇到在函数里调用其它函数的情况,这时候会有 fn() 这种调用方式,还有一种是 return fn() 这种调用方式,一些初学者经常会一脸萌逼地被这两种方式给绕晕了。这里用一个优雅的面试题来分析一下两种方式的不同之处。

var i = 0;
function fn(){
i++;
if(i < 10){
fn();
}else{
return i;
}
} var result = fn();
console.log(result);

这是一道隐藏了坑的面试题,看似很简单,大部分人可能想都不想就答出了10。而实际上运行可知打印出来的是 undefined。这道陷阱题很直观的体现出了前面所说的问题,当我们将执行fn的那一行修改为:

var i = 0;
function fn(){
i++;
if(i < 10){
return fn();
}else{
return i;
}
} var result = fn();
console.log(result);

这时,会发现打印出来的结果终于不负众望的是 10 了。

为什么这里加不加return区别会这么大?

这里的主要原因很简单,JavaScript的函数都是有默认返回值的,如果函数结尾不写return,会默认返回undefined,这就是为什么在chrome的console控制台里,写代码经常下面会出现一行undefined的原因。

再仔细看看这个例子,当i自增到9的时候,也就是倒数第二次递归调用fn的那一次,如果没有return,这一次执行完fn,会默认return undefined,而不会继续下一次递归了。当加上了 return,在这里则会继续最后一次递归,即i=10的时候,跳入else里面返回得到正确的10。

说到这里,可以引申出一个更为经典的例子,著名的二分查找法:

var mid = Math.floor((arr.length - 1) / 2);

function search(n, mid) {
if (n > arr[mid]) {
mid = Math.floor((mid + arr.length) / 2);
return search(n, mid);
} else if (n < arr[mid]) {
mid = Math.floor((mid - 1) / 2);
return search(n, mid);
} else {
return mid;
}
} var index = search(n, mid);
console.log(index);

二分查找法也是需要多次递归调用,很多新手在第一次实现这个算法的时候经常会犯的一个错误就是忘记在递归的函数前加上return,最后导致返回结果是undefined,这里的道理也和前面是类似的,不加return,会导致递归后,直接返回undefined,不会继续下一次递归。

深入理解JavaScript中 fn() 和 return fn() 的区别的更多相关文章

  1. 深入理解Javascript中构造函数和原型对象的区别

    在 Javascript中prototype属性的详解 这篇文章中,详细介绍了构造函数的缺点以及原型(prototype),原型链(prototype chain),构造函数(constructor) ...

  2. 深入理解Javascript中构造函数和原型对象的区别(转存)

    Object是构造函数,而Object.prototype是构造函数的原型对象.构造函数自身的属性和方法无法被共享,而原型对象的属性和方法可以被所有实例对象所共享. 首先,我们知道,构造函数是生成对象 ...

  3. 全面理解JavaScript中的 this

    全面理解JavaScript中的 this 上下文 VS 作用域 作用域(scope) 是在运行时代码中的某些特定部分中变量,函数和对象的可访问性.换句话 说,作用域决定了代码区块中变量和其他资源的可 ...

  4. 深入理解javascript中的立即执行函数(function(){…})()

    投稿:junjie 字体:[增加 减小] 类型:转载 时间:2014-06-12 我要评论 这篇文章主要介绍了深入理解javascript中的立即执行函数,立即执行函数也叫立即调用函数,通常它的写法是 ...

  5. 深入理解javascript中的立即执行函数

    这篇文章主要介绍了深入理解javascript中的立即执行函数,立即执行函数也叫立即调用函数,通常它的写法是用(function(){…})()包住业务代码,使用jquery时比较常见,需要的朋友可以 ...

  6. 深入理解JavaScript中创建对象模式的演变(原型)

    深入理解JavaScript中创建对象模式的演变(原型) 创建对象的模式多种多样,但是各种模式又有怎样的利弊呢?有没有一种最为完美的模式呢?下面我将就以下几个方面来分析创建对象的几种模式: Objec ...

  7. 深入理解JavaScript中的属性和特性

    深入理解JavaScript中的属性和特性 JavaScript中属性和特性是完全不同的两个概念,这里我将根据自己所学,来深入理解JavaScript中的属性和特性. 主要内容如下: 理解JavaSc ...

  8. 【干货理解】理解javascript中实现MVC的原理

    理解javascript中的MVC MVC模式是软件工程中一种软件架构模式,一般把软件模式分为三部分,模型(Model)+视图(View)+控制器(Controller); 模型:模型用于封装与应用程 ...

  9. 理解javascript中的策略模式

    理解javascript中的策略模式 策略模式的定义是:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换. 使用策略模式的优点如下: 优点:1. 策略模式利用组合,委托等技术和思想,有效 ...

  10. 全面理解Javascript中Promise

    全面理解Javascript中Promise 最近在学习Promise的时候,在网上收集了一些资料,发现很多的知识点不够系统,所以小编特意为大家整理了一些自认为 比较好的文章,供大家更好地学习js中非 ...

随机推荐

  1. tomcat 快速部署静态文件

    server.conf配置: <?xml version='1.0' encoding='utf-8'?> <!-- Licensed to the Apache Software ...

  2. Sql Server函数全解<二>数学函数

    阅读目录 1.绝对值函数ABS(x)和返回圆周率的函数PI() 2.平方根函数SQRT(x) 3.获取随机函数的函数RAND()和RAND(x) 4.四舍五入函数ROUND(x,y) 5.符号函数SI ...

  3. TransmitFile函数的简单使用

    简述 TransmitFile是一个扩展的 API,它允许在套接字连接上发送一个打开的文件.这使得应用程序可以避免亲自打开文件,重复地在文件执行读入操作,再将读入的那块数据写入套接字.相反,已打开的文 ...

  4. linux git实现代理

    说明  Git 目前支持的三种协议 git://.ssh:// 和 http://,使用git:// 和 http://比较多,ssh://忽略,FQ后可以直接加快同步google和github代码. ...

  5. MVC中使用Entity Framework 基于方法的查询学习笔记 (二)

    解释,不解释: 紧接上文,我们在Visual Studio2012中看到系统为我们自动创建的视图(View)文件Index.cshtml中,开头有如下这句话: @model IEnumerable&l ...

  6. Visual Studio 2015中创建C#的Android项目提示"Value cannot be null"的解决方法

    由于之前本机已安装过Android SDK,在安装Visual Studio 2015时跳过了,并没有为Xamarin指定对应路径导致.Visual Studio顶部菜单:Tools > Opt ...

  7. html图标插件

    https://bitbucket.org/cleonello/jqplot/downloads/ 下载地址 http://www.cnblogs.com/yaozhenfa/p/jqplot-pie ...

  8. 关于Vue vuex vux 文档

    01. vue 链接 http://vuejs.org.cn/guide/ 02. vuex  ----->>状态管理模块儿<<------- https://vuex.vue ...

  9. php阳历转农历的类 谷歌到的

    <?phpclass Lunar {    var $MIN_YEAR = 1891;    var $MAX_YEAR = 2100;    var $lunarInfo = array(   ...

  10. VO对象和PO对象的区别

    VO,值对象(Value Object),PO,持久对象(Persisent Object),它们是由一组属性和属性的get和set方法组成.从结构上看,它们并没有什么不同的地方.但从其意义和本质上来 ...