清风陪你学习-JavaScript高级(三)函数进阶、第一等公民、函数返回值

5函数进阶

学习目标

·       函数的声明调用参数等基本语法

·       理解作用域

·       闭包

·       this的指向和使用

·       改变this指向的方法

5.1 函数的声明及调用

关键字声明

 
functionf1(){
    console.log('f1');
}

表达式声明

 
varf2=function(){
    console.log('f2');
}

这种写法将一个匿名函数赋值给变量。这时,这个匿名函数又称函数表达式(Function Expression

构造函数方式声明

 
var add = new Function(
  'x',
  'y',
  'console.log( x + y )'
);
add(1,2);

上面代码与下面的代码等同;

 
// 等同于
function add(x, y) {
  console.log( x+y )
}
add(1,2);

因此,只关注前两种即可,后一种只做了解,不建议使用,这种声明函数的方式非常不直观,几乎无人使用;

那么,关键字声明表达式声明有什么区别?

·       关键字声明必须有名字

·       关键字声明会函数提升,在预解析阶段就已创建,声明前后都可以调用

·       函数表达式类似于变量赋值

·       函数表达式没有函数名字

·       函数表达式没有变量提升,在执行阶段创建,必须在表达式执行之后才可以调用

 
// 先调用后声明
f1();
function f1(){
    console.log('f1');
}
//由于变量提升,函数f被提升到了代码头部,也就是在调用之前已经声明了
//因此可以正常调用

而表达式方式:

 
f();
varf=function (){};
// TypeError: undefined is not a function

上面的代码等同于下面的形式。

 
varf;
f();
f=function () {};

上面代码第二行,调用f的时候,f只是被声明了,还没有被赋值,等于undefined,所以会报错。

因此,如果同时采用function命令和表达式声明同一个函数,最后总是采用表达式的定义。

 
varf=function () {
  console.log('1');
}
functionf() {
  console.log('2');
}
f() // 1

 

5.2 第一等公民

JavaScript 语言将函数看作一种,与其它值(数值、字符串、布尔值等等)地位相同。凡是可以使用值的地方,就能使用函数。比如,可以把函数赋值给变量和对象的属性,也可以当作参数传入其他函数,或者作为函数的结果返回。函数只是一个可以执行的值,此外并无特殊之处。

由于函数与其他数据类型地位平等,所以在 JavaScript 语言中又称函数为第一等公民

函数作为参数


function eat (callback) {
 
 setTimeout(function () {
 
   console.log('去嗨皮')
 
   callback()
 
}, 1000)
}

eat(function () {
 
 console.log('去唱歌')
})

函数作为返回值


function f1(){
 
   var s=1;
 
   function f2(){
 
       console.log(s);
 
  }
    return f2;
}
var f=f1();
f();// 1

JS中一切皆对象,函数也是对象,后面还会讲到

5.3 参数及返回值

5.3.1 参数

形参和实参


// 函数内部是一个封闭的环境,可以通过参数的方式,把外部的值传递给函数内部
// 带参数的函数声明
function 函数名(形参1, 形参2, 形参...){
 
 // 函数体
}

// 带参数的函数调用
函数名(实参1, 实参2, 实参3);

解释:

1.    形式参数:在声明一个函数的时候,为了函数的功能更加灵活,有些值是固定不了的,对于这些固定不了的值。我们可以给函数设置参数。这个参数没有具体的值,仅仅起到一个占位置的作用,我们通常称之为形式参数,也叫形参。

2.    实际参数:如果函数在声明时,设置了形参,那么在函数调用的时候就需要传入对应的参数,我们把传入的参数叫做实际参数,也叫实参。



function fn(a, b) {
 
 console.log(a+b);
}
var x=5, y=6;
fn(x,y);
//x,y实参,有具体的值。函数执行的时候会把x,y复制一份给函数内部的ab,函数内部的值是复制的新值,无法修改外部的x,y


var f = function (one) {
 
 console.log(one);
}
f(1, 2, 3)

由于 JavaScript 允许函数有不定数目的参数,所以需要一种机制,可以在函数体内部读取所有参数。

arguments对象函数的实参参数集合


var f=function (one) {
 
 console.log(arguments);
 
 console.log(arguments[0]);
 
 console.log(arguments[1]);
 
 console.log(arguments[2]);
}

f(1, 2, 3)

rest参数

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


// 只获取出a,b意外的参数
function foo(a, b) {
 
   var i , datas= [];
 
   if (arguments.length>2) {
 
       for (i=2; i<arguments.length; i++) {
 
          datas.push(arguments[i]);
 
       }
   }
    console.log('a = '+a);
 
   console.log('b = '+b);
 
   console.log(datas);
}
foo(1,2,3,4,5);

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

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

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

注意因为rest参数是ES6新标准,所以,请使用新型浏览器;

5.3.2 返回值

当函数执行完的时候,并不是所有时候都要把结果打印。我们期望函数给我一些反馈(比如计算的结果返回进行后续的运算),这个时候可以让函数返回一些东西。也就是返回值。函数通过return返回一个返回值


//声明一个带返回值的函数
function 函数名(形参1, 形参2, 形参...){
 
 //函数体
 
 return 返回值;
}

//可以通过变量来接收这个返回值
var 变量=函数名(实参1, 实参2, 实参3);

函数的调用结果就是返回值,因此我们可以直接对函数调用结果进行操作。

返回值详解如果函数没有显示的使用 return语句,那么这个函数就没有任何返回值,仅仅是执行了而已;如果函数使用 return语句,那么跟在return后面的值,就成了函数的返回值;如果函数使用 return语句,但是return后面没有任何值,那么函数的返回值也是:undefined ,

函数使用return语句后,这个函数会在执行完 return 语句之后停止并立即退出,也就是说return后面的所有其他代码都不会再执行。

return后没有任何内容,可以当做调试来使用;



猜你喜欢

转载自blog.csdn.net/Spirit_Breeze/article/details/80977112