JavaScript定义函数_动力节点Java学院整理


Posted in Javascript onJune 27, 2017

在JavaScript中,定义函数的方式如下:

function abs(x) {
 if (x >= 0) {
  return x;
 } else {
  return -x;
 }
}

上述abs()函数的定义如下:

  • function指出这是一个函数定义;
  • abs是函数的名称;
  • (x)括号内列出函数的参数,多个参数以,分隔;
  • { ... }之间的代码是函数体,可以包含若干语句,甚至可以没有任何语句。

请注意,函数体内部的语句在执行时,一旦执行到return时,函数就执行完毕,并将结果返回。因此,函数内部通过条件判断和循环可以实现非常复杂的逻辑。

如果没有return语句,函数执行完毕后也会返回结果,只是结果为undefined。

由于JavaScript的函数也是一个对象,上述定义的abs()函数实际上是一个函数对象,而函数名abs可以视为指向该函数的变量。

因此,第二种定义函数的方式如下:

var abs = function (x) {
  if (x >= 0) {
    return x;
  } else {
    return -x;
  }
};

在这种方式下,function (x) { ... }是一个匿名函数,它没有函数名。但是,这个匿名函数赋值给了变量abs,所以,通过变量abs就可以调用该函数。

上述两种定义完全等价,注意第二种方式按照完整语法需要在函数体末尾加一个;,表示赋值语句结束。

调用函数

调用函数时,按顺序传入参数即可:

abs(10); // 返回10
abs(-9); // 返回9

由于JavaScript允许传入任意个参数而不影响调用,因此传入的参数比定义的参数多也没有问题,虽然函数内部并不需要这些参数:

abs(10, 'blablabla'); // 返回10
abs(-9, 'haha', 'hehe', null); // 返回9

传入的参数比定义的少也没有问题:

abs(); // 返回NaN

此时abs(x)函数的参数x将收到undefined,计算结果为NaN。

要避免收到undefined,可以对参数进行检查:

function abs(x) {
  if (typeof x !== 'number') {
    throw 'Not a number';
  }
  if (x >= 0) {
    return x;
  } else {
    return -x;
  }
}

arguments

JavaScript还有一个免费赠送的关键字arguments,它只在函数内部起作用,并且永远指向当前函数的调用者传入的所有参数。arguments类似Array但它不是一个Array:

function foo(x) {
  alert(x); // 10
  for (var i=0; i<arguments.length; i++) {
    alert(arguments[i]); // 10, 20, 30
  }
}
foo(10, 20, 30);

利用arguments,你可以获得调用者传入的所有参数。也就是说,即使函数不定义任何参数,还是可以拿到参数的值:

function abs() {
  if (arguments.length === 0) {
    return 0;
  }
  var x = arguments[0];
  return x >= 0 ? x : -x;
}
abs(); // 0
abs(10); // 10
abs(-9); // 9

实际上arguments最常用于判断传入参数的个数。你可能会看到这样的写法:

// foo(a[, b], c)
// 接收2~3个参数,b是可选参数,如果只传2个参数,b默认为null:
function foo(a, b, c) {
  if (arguments.length === 2) {
    // 实际拿到的参数是a和b,c为undefined
    c = b; // 把b赋给c
    b = null; // b变为默认值
  }
  // ...
}

要把中间的参数b变为“可选”参数,就只能通过arguments判断,然后重新调整参数并赋值。

rest参数

由于JavaScript函数允许接收任意个参数,于是我们就不得不用arguments来获取所有参数:

function foo(a, b) {
  var i, rest = [];
  if (arguments.length > 2) {
    for (i = 2; i<arguments.length; i++) {
      rest.push(arguments[i]);
    }
  }
  console.log('a = ' + a);
  console.log('b = ' + b);
  console.log(rest);
}

为了获取除了已定义参数a、b之外的参数,我们不得不用arguments,并且循环要从索引2开始以便排除前两个参数,这种写法很别扭,只是为了获得额外的rest参数,有没有更好的方法?

ES6标准引入了rest参数,上面的函数可以改写为:

function foo(a, b, ...rest) {
  console.log('a = ' + a);
  console.log('b = ' + b);
  console.log(rest);
}
foo(1, 2, 3, 4, 5);
// 结果:
// a = 1
// b = 2
// Array [ 3, 4, 5 ]
foo(1);
// 结果:
// a = 1
// b = undefined
// Array []

rest参数只能写在最后,前面用...标识,从运行结果可知,传入的参数先绑定a、b,多余的参数以数组形式交给变量rest,所以,不再需要arguments我们就获取了全部参数。

如果传入的参数连正常定义的参数都没填满,也不要紧,rest参数会接收一个空数组(注意不是undefined)。

因为rest参数是ES6新标准,所以你需要测试一下浏览器是否支持。请用rest参数编写一个sum()函数,接收任意个参数并返回它们的和:

窗体顶端

'use strict';
// 测试:
var i, args = [];
for (i=1; i<=100; i++) {
  args.push(i);
}
if (sum() !== 0) {
  alert('测试失败: sum() = ' + sum());
} else if (sum(1) !== 1) {
  alert('测试失败: sum(1) = ' + sum(1));
} else if (sum(2, 3) !== 5) {
  alert('测试失败: sum(2, 3) = ' + sum(2, 3));
} else if (sum.apply(null, args) !== 5050) {
  alert('测试失败: sum(1, 2, 3, ..., 100) = ' + sum.apply(null, args));
} else {
  alert('测试通过!');
}

小心你的return语句

前面我们讲到了JavaScript引擎有一个在行末自动添加分号的机制,这可能让你栽到return语句的一个大坑:

function foo() {
  return { name: 'foo' };
}
foo(); // { name: 'foo' }

如果把return语句拆成两行:

function foo() {
  return
    { name: 'foo' };
}
foo(); // undefined

要小心了,由于JavaScript引擎在行末自动添加分号的机制,上面的代码实际上变成了:

function foo() {
  return; // 自动添加了分号,相当于return undefined;
    { name: 'foo' }; // 这行语句已经没法执行到了
}

所以正确的多行写法是:

function foo() {
  return { // 这里不会自动加分号,因为{表示语句尚未结束
    name: 'foo'
  };
}

练习

定义一个计算圆面积的函数area_of_circle(),它有两个参数:

r: 表示圆的半径;

pi: 表示π的值,如果不传,则默认3.14

Javascript 相关文章推荐
jcarousellite.js 基于Jquery的图片无缝滚动插件
Dec 30 Javascript
input 输入框获得/失去焦点时隐藏/显示文字(jquery版)
Apr 02 Javascript
Extjs中RowExpander控件的默认展开问题示例探讨
Jan 24 Javascript
javascript实现了照片拖拽点击置顶的照片墙代码
Apr 03 Javascript
javascript实现保留两位小数的多种方法
Dec 18 Javascript
JS实现图片的不间断连续滚动的简单实例
Jun 03 Javascript
简单介绍react redux的中间件的使用
Apr 06 Javascript
JavaScript折半查找(二分查找)算法原理与实现方法示例
Aug 06 Javascript
vue组件中的样式属性scoped实例详解
Oct 30 Javascript
整理 node-sass 安装失败的原因及解决办法(小结)
Feb 19 Javascript
viewer.js一个强大的基于jQuery的图像查看插件(支持旋转、缩放)
Apr 01 jQuery
vue-cli4项目开启eslint保存时自动格式问题
Jul 13 Javascript
详解vue项目构建与实战
Jun 27 #Javascript
微信小程序 蓝牙的实现实例代码
Jun 27 #Javascript
微信小程序 开发MAP(地图)实例详解
Jun 27 #Javascript
微信小程序商品到详情的实现
Jun 27 #Javascript
微信小程序的分类页面制作
Jun 27 #Javascript
JS实现批量上传文件并显示进度功能
Jun 27 #Javascript
angular过滤器实现排序功能
Jun 27 #Javascript
You might like
Apache2 httpd.conf 中文版
2006/12/06 PHP
PHP学习 变量使用总结
2011/03/24 PHP
PHP常见漏洞攻击分析
2016/02/21 PHP
PHP常用的类封装小结【4个工具类】
2019/06/28 PHP
js 浮动层菜单收藏
2009/01/16 Javascript
jquery提升性能最佳实践小结
2010/12/06 Javascript
js中如何把字符串转化为对象、数组示例代码
2013/07/17 Javascript
js的alert样式如何更改如背景颜色
2014/01/22 Javascript
jQuery实现折叠、展开的菜单组效果代码
2015/09/16 Javascript
详解JavaScript中的构造器Constructor模式
2016/01/14 Javascript
jQuery简易时光轴实现方法示例
2017/03/13 Javascript
angularjs定时任务的设置与清除示例
2017/06/02 Javascript
微信分享调用jssdk实例
2017/06/08 Javascript
微信小程序之滚动视图容器的实现方法
2017/09/26 Javascript
vue-cli 首屏加载优化问题
2018/11/06 Javascript
jQuery实现获取当前鼠标位置并输出功能示例
2019/01/05 jQuery
详解单页面路由工程使用微信分享及二次分享解决方案
2019/02/22 Javascript
微信小程序解析富文本过程详解
2019/07/13 Javascript
AI小程序之语音听写来了,十分钟掌握百度大脑语音听写全攻略
2020/03/13 Javascript
[50:12]EG vs Fnatic 2018国际邀请赛小组赛BO2 第二场 8.19
2018/08/21 DOTA
java直接调用python脚本的例子
2014/02/16 Python
Python多线程编程(三):threading.Thread类的重要函数和方法
2015/04/05 Python
详解Python进程间通信之命名管道
2017/08/28 Python
Pandas标记删除重复记录的方法
2018/04/08 Python
对python自动生成接口测试的示例讲解
2018/11/30 Python
Python实现的对本地host127.0.0.1主机进行扫描端口功能示例
2019/02/15 Python
在PyCharm中安装PaddlePaddle的方法
2021/02/05 Python
css3 实现圆形旋转倒计时
2018/02/24 HTML / CSS
伦敦高级内衣品牌:Agent Provocateur(大内密探)
2016/08/23 全球购物
elf彩妆英国官网:e.l.f. Cosmetics英国(美国平价彩妆品牌)
2017/11/02 全球购物
印尼综合在线预订网站:Tiket.com(机票、酒店、火车、租车和娱乐)
2018/10/11 全球购物
在校生汽车维修实习自我鉴定
2013/09/19 职场文书
党的群众路线个人对照检查材料
2014/09/23 职场文书
超市主管竞聘书
2015/09/15 职场文书
redis 解决库存并发问题实现数量控制
2022/04/08 Redis
Go语言 详解net的tcp服务
2022/04/14 Golang