02函数-01-函数的定义和调用

1、定义函数

  1. function abs(x) {
  2. if (x >= 0) {
  3. return x;
  4. } else {
  5. return -x;
  6. }
  7. }

如果没有return,函数执行完毕也会返回结果,不过结果是undefined。

由于在JS的世界中,函数也是一个对象,所以上述定义的函数实际上也是一个对象,而函数名则可视为指向该函数的变量。

所以上面的函数定义等价于:

  1. var abs = function (x) {
  2. if (x >= 0) {
  3. return x;
  4. } else {
  5. return -x;
  6. }
  7. };

2、调用函数

JS的函数允许任意个,也不影响调用,接以上的abs函数:

  1. //比定义的参数多
  2. abs(10, ‘blablabla‘); // 返回10
  3. abs(-9, ‘haha‘, ‘hehe‘, null); // 返回9
  4. //比定义的参数少
  5. abs(); // 返回NaN --> 此时abs(x)函数的参数x将收到undefined,计算结果为NaN

JS中有个关键字 arguments,只在函数内部起作用,永远指向当前函数的调用者传入的所有参数,类似Array但不是Array:

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

  1. // foo(a[, b], c)
  2. // 接收2~3个参数,b是可选参数,如果只传2个参数,b默认为null:
  3. function foo(a, b, c) {
  4. if (arguments.length === 2) {
  5. // 实际拿到的参数是a和b,c为undefined
  6. c = b; // 把b赋给c
  7. b = null; // b变为默认值
  8. }
  9. // ...
  10. //要把中间的参数b变为“可选”参数,就只能通过arguments判断,然后重新调整参数并赋值
  11. }

为了获得多余的参数,我们也就是利用arguments,但是稍微有点不方便:

  1. function foo(a, b) {
  2. var i, rest = [];
  3. if (arguments.length > 2) {
  4. for (i = 2; i<arguments.length; i++) {
  5. rest.push(arguments[i]);
  6. }
  7. }
  8. console.log(‘a = ‘ + a);
  9. console.log(‘b = ‘ + b);
  10. console.log(rest);
  11. }

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

  1. function foo(a, b, ...rest) {
  2. console.log(‘a = ‘ + a);
  3. console.log(‘b = ‘ + b);
  4. console.log(rest);
  5. }
  6. foo(1, 2, 3, 4, 5);
  7. // 结果:
  8. // a = 1
  9. // b = 2
  10. // Array [ 3, 4, 5 ]
  11. foo(1);
  12. // 结果:
  13. // a = 1
  14. // b = undefined
  15. // Array []
  16. //如果传入的参数连正常定义的参数都没填满,也不要紧,rest参数会接收一个空数组(注意不是undefined)

拓展思维:

  1. //用rest参数编写一个sum()函数,接收任意个参数并返回它们的和
  2. ‘use strict‘;
  3. function sum(...rest) {
  4. var result = 0;
  5. for(var value of rest){
  6. result += value;
  7. };
  8. return result;
  9. }
  10. // 测试:
  11. var i, args = [];
  12. for (i=1; i<=100; i++) {
  13. args.push(i);
  14. }
  15. if (sum() !== 0) {
  16. alert(‘测试失败: sum() = ‘ + sum());
  17. } else if (sum(1) !== 1) {
  18. alert(‘测试失败: sum(1) = ‘ + sum(1));
  19. } else if (sum(2, 3) !== 5) {
  20. alert(‘测试失败: sum(2, 3) = ‘ + sum(2, 3));
  21. } else if (sum.apply(null, args) !== 5050) {
  22. alert(‘测试失败: sum(1, 2, 3, ..., 100) = ‘ + sum.apply(null, args));
  23. } else {
  24. alert(‘测试通过!‘);
  25. }
  1. //定义一个计算圆面积的函数area_of_circle(),它有两个参数:r: 表示圆的半径;pi: 表示π的值,如果不传,则默认3.14
  2. ‘use strict‘;
  3. function area_of_circle(r, pi) {
  4. var temp = 3.14;
  5. if(arguments.length > 1){
  6. temp = pi;
  7. }
  8. return temp*r*r;
  9. }
  10. // 测试:
  11. if (area_of_circle(2) === 12.56 && area_of_circle(2, 3.1416) === 12.5664) {
  12. alert(‘测试通过‘);
  13. } else {
  14. alert(‘测试失败‘);
  15. }
  16. //网友答约:pi=pi?pi:3.14; return pi*r*r;

3、变量作用域

在JavaScript中,我们说如果一个变量不用var申明,那么默认作为全局变量。而我们使用了var申明的变量,实际上也是有作用域的。

  • 如果函数内申明,则函数体外不可引用
  • 函数可以嵌套,内部函数的变量可以访问外部函数的变量,反之不可
  • 内部与外部变量重名的话,查找变量从内往外,则屏蔽外部函数变量

JS中的变量申明会“提升”到函数顶部,赋值不提升,这句话是什么意思呢?看下面的代码:

  1. ‘use strict‘;
  2. function foo() {
  3. var x = ‘Hello, ‘ + y;
  4. alert(x);
  5. var y = ‘Bob‘;
  6. }
  7. foo();

y虽然申明在x之后,但是 var x = ‘Hello,‘ + y 并不会报错(这就是变量申明的提升),但是alert出来的是 Hello, undefined,即y的值还是undefined(这就是赋值不提升)。

实际上JavaScript引擎看到的代码相当于:

  1. function foo() {
  2. var y; // 提升变量y的申明
  3. var x = ‘Hello, ‘ + y;
  4. alert(x);
  5. y = ‘Bob‘;
  6. }

这个特性其实并没有什么好处,反而容易让人犯错,所以按像Java语言中一样的变量申明习惯就好了,需要用的变量先申明,再使用。

3.1 全局作用域

JavaScript默认有一个全局对象window,全局作用域的变量实际上被绑定到window的一个属性,因此,假如你定义了一个全局作用域的变量 test,那么是直接访问test和访问window.test是一样的。

由于函数定义也有两种方式,其中以变量方式定义的函数实际上也是一个全局变量,被绑定在window对象,你可以通过 window.test() 类似的方法调用,事实上,alert()方法也是window的一个变量!

全局变量会绑定在window上,那么当你引入不同的文件,文件之间如果用到了相同的全局变量或同名函数,就会造成命名冲突,并且很难被发现。

减少冲突的一个方法就是把自己的所有的全局变量和函数,全部绑定到一个全局变量中:

  1. // 唯一的全局变量MYAPP:
  2. var MYAPP = {};
  3. // 其他变量:
  4. MYAPP.name = ‘myapp‘;
  5. MYAPP.version = 1.0;
  6. // 其他函数:
  7. MYAPP.foo = function () {
  8. return ‘foo‘;
  9. };
  10. //把自己的代码全部放入唯一的名字空间MYAPP中,会大大减少全局变量冲突的可能

3.2 局部作用域

在之前我的理解,比如在函数内定义的变量,因为作用域在函数内,所以就算是局部作用域了,而下面的代码:

  1. ‘use strict‘;
  2. function foo() {
  3. for (var i=0; i<100; i++) {
  4. //
  5. }
  6. i += 100; // 仍然可以引用变量i
  7. }

即是说,实际上这种默认方式的作用域并不完全是局部的,至少在for循环语句块中的作用域,在for循环之外还可以引用(妈呀JavaScript不愧是10天写出来的函数,确实很厉害但是有些地方真的很讨厌),为了解决这个问题,ES6引入了新的关键字 let,这个可以替代var申明一个块级作用域的变量:

  1. ‘use strict‘;
  2. function foo() {
  3. var sum = 0;
  4. for (let i=0; i<100; i++) {
  5. sum += i;
  6. }
  7. i += 1; // SyntaxError
  8. }

3.3 常量

在ES6标准之前,我们表示常量通常都使用全部大写的方式来“告诉“使用者,不要修改它的值,但实际上这个值是可以被修改了,是存在风险的。在ES6标准中引入了新的关键字const,可以申明不可改变的常量,且同let一样具有块级作用域。

时间: 2024-07-31 14:35:14

02函数-01-函数的定义和调用的相关文章

JS中函数的本质,定义、调用,以及函数的参数和返回值

要用面向对象的方式去编程,而不要用面向过程的方式去编程 对象是各种类型的数据的集合,可以是数字.字符串.数组.函数.对象…… 对象中的内容以键值对方式进行存储 对象要赋值给一个变量 var cat={ "name":"喵1", "age":4, "family":["喵爸","喵妈"], "speak":function(){ console.log("喵喵

ios开发Swif语言基本的参数、函数、方法的定义和调用

把老师讲得知识和大家分享下咯,希望大家提出疑问,这是我综合自己理解和老师讲得敲出来的! //var str = "Hello, playground" //定义变量 let a0:Int = 5; //定义函数 func test() { print("asdfg") } test() //定义带参数并且有返回值的参数 func test1(a: Int) ->Int { return 100; } test1(100) //Swift 语言代码后面可以加;结

函数,函数的四种定义,

函数 1.函数的关键字  function 复习 var 是js的关键字,用于表示声明变量,声明是在内存模块完成,定义(=)是执行模块完成. var 客园在内存模块提前(js代码执行前)完成所以有变量提升这个功能. function 也是js1的关键字,用于声明和定义函数的,声明和定义都在内存模块完成. function 也是内存模块提前完成,所以有函数提升这个功能. 变量提升和函数提升 都叫预解释.都是浏览器的. 2,函数的定义:函数具有一定的功能的代码块. 函数是通过function 定义的

(一)Python入门-5函数:01函数的基本概念-内存分析-函数的分类-定义和调用

一:函数介绍 函数是可重用的程序代码块.函数的作用,不仅可以实现代码的复用,更能实现代码的 一致性.一致性指的是,只要修改函数的代码,则所有调用该函数的地方都能得到体现. 在编写函数时,函数体中的代码写法和我们前面讲述的基本一致,只是对代码实现了封 装,并增加了函数调用.传递参数.返回计算结果等内容. 函数基本概念: 1. 一个程序由一个个任务组成:函数就是代表一个任务或者一个功能. 2. 函数是代码复用的通用机制. 二:Python函数的分类 Python中函数分为如下几类: 1. 内置函数

Bash脚本之函数定义和调用

把那些在脚本中重复出现并且没有任何改变的代码,封装起来,在适当的场景中调用执行.程序员将这种被封装起来的代码称为功能体,或者叫模块,也称为函数.这样看来是不是和循环类似,循环也是为了方便去多次执行一堆代码,而函数是将一堆代码写在一起,起一个名字,然后在需要这堆代码的时候只需要写上函数的名字即可.在shell脚本编程中,函数是由若干条shell命令组成的语句块,函数里面的内容和shell程序形式上是一致的.不同之处就是,shell代码可以直接被执行,而函数中的内容,不能独立执行,只有被调用的时候才

实验八——函数定义及调用总结

实验八--函数定义及调用总结 1.本次课学习到的知识点: (1)void为不反回结果的函数,且void不能省略,否则默认为int,函数体中没有表达式的return语句,也可省略return. (2)不返回结果的函数在定义.调用.参数传递.函数声明上,思路与以前相同,适用于把一些确定的.相对独立的程序功能封装成函数. (3)局部变量:定义在函数的内部,且有效作用范局部变量一般定义在函数或复合语句的开始处,围局限于所在的函数内部,形参是局部变量. (4)不能定义在中间位置. (5)全局变量:定义在函

实验七——函数定义及调用总结

1.本次课学习到的知识点: 函数 (1)定义:函数是一个完成特定工作的独立程序模块,包括函数和自定义函数两种: 1.scanf(),printf()等为库函数,由c语言系统提供定义,编程时只要直接调用即可. 2. cylinder(),fact()函数,需要用户自己定义,为自定义函数. (2)cylinder(),fact()功能不同,但他们能实现一个计算,并可以得到一个明确的计算结果. (3) 函数定义的一般形式为: 函数类型    函数名(形式参数表) { 函数实现过程 } (4)函数部首:

第9课 - 函数定义及调用

第9课 - 函数定义及调用 1. makefile中的函数 (1)make 解释器提供了一系列的函数供 makefile 调用 (2)在 makefile 中支持自定义函数实现,并调用执行 (3)通过 define 关键字实现自定义函数 2. 在makefile中自定义函数 (1)自定义函数的语法 其中,$(0) 代表被调用的函数名,$(1) , $(2) , $(3) ... 代表调用函数时后面的传参 (2)深入理解自定义函数 - 自定义函数是一个多行变量,无法直接调用 - 自定义函数是一种过

实验八--函数定义及调用总结

本次课学习到的知识点: 函数分成库函数和定义函数两种,库函数在编程是可以直接调用,定义函数需要自己定义,他们也有共同的特点就是能实现一个运算,并且得到一个明确的计算结果. 函数首部由函数类型,函数名和形式参数组成,位于函数定义的第一行,形参用于给出函数计算所要的函数结果和返回类型,形参表中各个形参用逗号分隔. 实际参数可以是常量,变量,表达式.形参必须是变量. 形参和实参必须一一对应,由实参一一传递给形参. 试验中遇到的问题及解决办法: 在金字塔的实验中进入了死循环,最后发现没有添加scanf语