JavaScript快速入门-06-函数

6 函数

6.1 函数定义

    函数可以封装语句,然后在任何地方、任何时间执行。JavaScript中的函数使用function关键字声明,主要由函数名函数参数函数体组成。其基本语法和声明如下所示:

  • 方式一:
function functionName(arg0, arg1,...,argN) {
    statements
}
  • 方式二:
let variable=function(arg0, arg1,...,argN) {
    statements
}
  • 方式三:
let variable=(arg0, arg1,...,argN) => {
    statements
}
  • 如果函数无返回值,则不需要return语句,如果有返回值,则需要return语句
  • 在碰到return语句后,则立即返回,后续语句不再执行

    示例如下所示:

// 无返回值函数
function hello(name){
    console.log("Hello ,",name);
}
// 存在返回值函数
function sum(number1,number2){
    return number1+number2;
}

// 遇到return语句,提前返回
function testReturn(age){
   return "test return ";
   console.log("age is:",age);

}

// 使用函数表达式定义函数
let diff=function(number1,number2){
    return number1-number2
}

// 箭头函数
let mul=(number1,number2) =>{
    return number1*number2;
}

hello("Surpass");
console.log("sum is :",sum(7,18));
console.log(testReturn(18));
console.log("diff is:",diff(7,18));
console.log("mul is:",mul(7,18));

输出结果如下所示:

Hello , Surpass
sum is : 25
test return
diff is: -11
mul is: 126

6.2 箭头函数

    箭头函数实例化的函数对象与正式的函数表达式创建的函数对象行为是相同的。任何可以使用函数表达式的地方,都可以使用箭头函数。需要注意事项如下所示:

  • 1、在仅有一个参数时,可以省略括号,以下两种写法完全等效:
let absValue1=(x)=>{return Math.abs(x);};
let absValue2=x=>{return Math.abs(x);};
  • 2、当没有参数时,括号不能省略
let getRandomNumber=()=>{return Math.random()*10;};
  • 3、多个参数也需要括号
let div=(a,b)=>{
    if(b!=0){
        return a/b;
    }
    else{
        return Infinity;
    }
};
  • 4、大括号省略注意事项:

箭头函数也可以不使用大括号,但这样会改变函数的行为。使用大括号就说明包含函数体,即可以在一个函数中包含多条语句,跟常规函数一样。如果不使用大括号,则箭头后面就只能有一行代码,如一个表达式、赋值操作等。而且,省略大括号会隐式返回这行代码的值。

    示例代码如下所示:

// 以下两种写法都有效
let power1=(x)=>{return x**2;};
let power2=x=>x**2;

console.log("power1 is:"+power1(2)+"\npower2 is:"+power2(2));

// 进行赋值操作
let personInfo={};
let setPersonInfoName=(name)=>personInfo.name=name;
setPersonInfoName("Surpass");
console.log("personInfo is:",personInfo);

// 无效写法
let sum=(number1,number2)=> return number1+number2;

    箭头函数虽然语法简洁,但也有很多场合不适用。箭头函数不能使用arguments、super 和new.target,也不能用作构造函数。此外,箭头函数也没有prototype属性

6.3 函数名

    因为函数名就是指向函数的指针,所以它们跟其他包含对象指针的变量具有相同的行为。即一个函数可以有多个名称,如下所示:

function sum(number1,number2){
    return number1+number2;
}

console.log("Sum is: ",sum(10,18)); // 28

let refSum=sum;
console.log("refSum is: ",refSum(10,18)); // 28

sum=null;
console.log("refSum is: ",refSum(10,18)); // 28

    以上代码定义了sum()的函数,并将sum赋值给refSum,使用不带括号的函数名会访问函数指针,并不会执行函数。此时,refSum和sum都指向同一个函数。调用refSum()也可以返回结果。再将sum赋为null之后,就切断了它与函数之间的关联,所以refSum()依然可以照常调用。

6.4 函数参数

    在JavaScript中,函数不关心传入的参数个数数据类型。其函数参数,在内部表现一个数组,因此函数调用时都会接收到一个数组,函数并不关心数组中包含什么。

1.定义函数时,声明有两个参数,在调用时并不一定就需要传入两个参数,也可以传一个,两个,三个或不传,解释器也并不会报错。
2.在使用function关键字定义(非箭头)函数,可以在函数内部访问arguments对象,从中获取传入的每个参数值

// 使用参数一
function hello_1(name,message){
    console.log("call function ",hello_1.name);
    return "Hello"+name+message;
}
// 使用参数二:arguments
function hello_2(){
    console.log("call function ",hello_2.name);
    console.log("input para length is:",arguments.length);
    return "Hello"+arguments[0]+arguments[1];
}

console.log(hello_1(" Surpass"," Welcome to Shanghai"));
console.log(hello_2(" Surpass"," Welcome to Shanghai"));

输出结果如下所示:

call function  hello_1
Hello Surpass Welcome to Shanghai
call function  hello_2
input para length is: 2
Hello Surpass Welcome to Shanghai

    在函数中,arguments对象可以跟参数一起使用,如下所示:

function add(number1,number2){
   let paraLength=arguments.length;
   if (paraLength == 1){
       return number1;
   } else if (paraLength ==2 ){
      return arguments[0]+number2;
   } else {
       let sum=0;
       for(let item of arguments){
          sum+=item;
       }
       return sum;
   }
}

console.log("result is:",add(1));
console.log("result is:",add(1,2));
console.log("result is:",add(1,2,3));

输出结果如下所示:

result is: 1
result is: 3
result is: 6

如果函数是箭头函数,则传入的参数不能再使用arguments关键字访问,而只能通过定义的参数名称来访问

6.5 没有重载

    JavaScript不像Java/C#等,存在函数重载功能。因为在JavaScript中函数不一定有函数名称,参数可以是0个或多个,所以自然就没有重载功能。如果在JavaScript中定义了两个同名函数,则后面定义的函数会覆盖前面定义的函数。示例如下所示:

function sum(){
    return arguments[0]+28;
}

function sum(){
    return arguments[0]+128;
}

let result=sum(100);
console.log("result is:",result) // 228

6.6 参数默认值

    在ECMAScript5.1 及以前,默认参数值为undefined,而在ECMAScript 6 之后,则可以支持显式定义默认参数了,如下所示:

  • 1.给参数传undefined 相当于没有传值,好处是可以利用多个独立的默认值
function hello(name="Surpass",message=" Welcome"){
    return `Hello  ${name} ${message}`;
}

console.log(hello()); // Hello Surpass  Welcome
console.log(hello("Kevin","Welcome to Shanghai")); // Hello Kevin Welcome to Shanghai
console.log(hello(undefined,"Welcome to Shanghai")); // Hello Surpass Welcome to Shanghai
  • 2.在使用默认参数时,arguments 对象的值不反映参数的默认值,只反映传给函数的参数,,修改命名参数也不会影响arguments 对象,它始终以调用函数时传入的值为准
function hello(name="Surpass",message=" Welcome"){
    name="Kevin";
    return `Hello  ${arguments[0]} ${message}`;
}

console.log(hello()); // Hello  undefined  Welcome
console.log(hello("Kevin","Welcome to Shanghai")); // Hello Kevin Welcome to Shanghai
  • 3.默认参数值并不限于原始值或对象类型,也可以使用调用函数返回的值
let name=["Surpass","Kevin","Tina","Jeniffer"];
let city=["Shanghai","Wuhan","Nanjing","Suzhou"];
let nameIndex=0,cityIndex=0;

function getCity(){
    // 每次调用后递增
    return city[cityIndex++];
}

function getName(){
  return name[nameIndex++];
}

function hello(name=getName(),message=getCity()){
   return `Hello ${name},Welcome ${message}`;
}

for (let i = 0; i < city.length; i++) {
    console.log(hello());
}

输出结果如下所示:

Hello Surpass,Welcome Shanghai
Hello Kevin,Welcome Wuhan
Hello Tina,Welcome Nanjing
Hello Jeniffer,Welcome Suzhou

函数的默认参数只有在函数被调用时才会求值,不会在函数定义时求值

  • 4.箭头函数同样也可以使用默认参数,但在仅有一个参数时,则不能省略括号
let hello=(name="Surpass")=>{return `Hello ${name}`;}

console.log(hello()); // Hello Surpass 
console.log(hello("Kevin")); // Hello Kevin

6.7 参数扩展和收集

    ECMAScript 6 新增了扩展操作符,使用它可以非常简洁地操作和组合集合数据。扩展操作符最有用的场景就是函数定义中的参数列表。既可以用于调用函数时传参,也可以用于定义函数参数。

6.7.1 扩展参数

    先来看看示例代码,如下所示:

function sum(){
    let sum=0;
    for (let index = 0; index < arguments.length; index++) {
        sum+=arguments[index];
    }
    return sum;
}
let number=[1,2,3,4,5];
console.log("sum is :",sum(number)); // sum is : 01,2,3,4,5

    以上函数功能是希望将传入的参数进行累加处理。如果不使用扩展操作符,则需要在传入函数前,将参数进行拆分处理,可以使用apply()方法

console.log("sum is :",sum.apply(null,number)); // sum is : 15

    在ECMAScript 6 中,可以通过扩展操作符实现这种操作。对可迭代对象应用扩展操作符,并将其作为一个参数传入,可将可迭代对象拆分,并将迭代返回的每个值单独传入。示例如下所示:

function sum(){
    let sum=0;
    for (let index = 0; index < arguments.length; index++) {
        sum+=arguments[index];
    }
    return sum;
}

let number=[1,2,3,4,5];
// 使用扩展操作符
console.log("sum is :",sum(...number));  // sum is : 15

    因为数组的长度已知,所以在使用扩展操作符传参的时候,并不妨碍在其前面或后面再传其他的值,包括使用扩展操作符传其他参数,示例如下所示:

console.log("sum is :",sum(-10,...number)); // sum is : 5
console.log("sum is :",sum(-10,...number,95)); // sum is : 100
console.log("sum is :",sum(-10,...number,...[1,2,3,4],10)); // sum is : 25

扩展参数操作符其主要作用是将传入的参数进行拆分为单个元素。

6.7.2 收集参数

    先来看看示例代码,如下所示:

function getArray(...numbers){
    return numbers;
}

console.log(getArray(1,2,3)) // [ 1, 2, 3 ]

在定义函数时,可以使用扩展操作符把不同长度的独立参数组合为一个数组(类似arguments对象的构造机制,收集参数的结果会得到一个数组实例),

    在使用收集参数操作符,注意事项如下所示:

  • 收集参数只能位于命名参数之后(因为收集参数的结果可变,因此仅能做为最后一个参数)
  • 收集参数前面如果有命令参数,则仅会收集其余的参数
  • 箭头函数支持收集参数操作符
// 不可以这样定义
function getArrayA(...value,lastPara){}

// 必须要这样声明
function getArrayB(firstPara,...numbers){
    return numbers;
}
// 箭头函数支持收集参数
let getArrayC=(...values) =>{return values;};

console.log(getArrayB()) // []
console.log(getArrayB(1,2,3)) // [ 2, 3 ]
console.log(getArrayB(1,2,3,4,5,6)) // [2, 3, 4, 5, 6]
console.log(getArrayC(1,2,3,4,5,6)) // [1, 2, 3, 4, 5, 6]
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,233评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,013评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,030评论 0 241
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,827评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,221评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,542评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,814评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,513评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,225评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,497评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,998评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,342评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,986评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,812评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,560评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,461评论 2 266

推荐阅读更多精彩内容