草庐IT

JavaScript快速入门-06-函数

Surpassme 2023-03-28 原文

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]

原文地址:https://www.jianshu.com/p/07328d8a31f7

本文同步在微信订阅号上发布,如各位小伙伴们喜欢我的文章,也可以关注我的微信订阅号:woaitest,或扫描下面的二维码添加关注:

有关JavaScript快速入门-06-函数的更多相关文章

  1. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

    我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

  2. ruby-on-rails - 在 ruby​​ 中使用 gsub 函数替换单词 - 2

    我正在尝试用ruby​​中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了

  3. ruby - 在 Ruby 中有条件地定义函数 - 2

    我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin

  4. ruby - 在 Ruby 中按名称传递函数 - 2

    如何在Ruby中按名称传递函数?(我使用Ruby才几个小时,所以我还在想办法。)nums=[1,2,3,4]#Thisworks,butismoreverbosethanI'dlikenums.eachdo|i|putsiend#InJS,Icouldjustdosomethinglike:#nums.forEach(console.log)#InF#,itwouldbesomethinglike:#List.iternums(printf"%A")#InRuby,IwishIcoulddosomethinglike:nums.eachputs在Ruby中能不能做到类似的简洁?我可以只

  5. C51单片机——实现用独立按键控制LED亮灭(调用函数篇) - 2

    说在前面这部分我本来是合为一篇来写的,因为目的是一样的,都是通过独立按键来控制LED闪灭本质上是起到开关的作用,即调用函数和中断函数。但是写一篇太累了,我还是决定分为两篇写,这篇是调用函数篇。在本篇中你主要看到这些东西!!!1.调用函数的方法(主要讲语法和格式)2.独立按键如何控制LED亮灭3.程序中的一些细节(软件消抖等)1.调用函数的方法思路还是比较清晰地,就是通过按下按键来控制LED闪灭,即每按下一次,LED取反一次。重要的是,把按键与LED联系在一起。我打算用K1来作为开关,看了一下开发板原理图,K1连接的是单片机的P31口,当按下K1时,P31是与GND相连的,也就是说,当我按下去时

  6. LC滤波器设计学习笔记(一)滤波电路入门 - 2

    目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称

  7. 微信小程序开发入门与实战(Behaviors使用) - 2

    @作者:SYFStrive @博客首页:HomePage📜:微信小程序📌:个人社区(欢迎大佬们加入)👉:社区链接🔗📌:觉得文章不错可以点点关注👉:专栏连接🔗💃:感谢支持,学累了可以先看小段由小胖给大家带来的街舞👉微信小程序(🔥)目录自定义组件-behaviors    1、什么是behaviors    2、behaviors的工作方式    3、创建behavior    4、导入并使用behavior    5、behavior中所有可用的节点    6、同名字段的覆盖和组合规则总结最后自定义组件-behaviors    1、什么是behaviorsbehaviors是小程序中,用于实现

  8. 【Java入门】使用Java实现文件夹的遍历 - 2

    遍历文件夹我们通常是使用递归进行操作,这种方式比较简单,也比较容易理解。本文为大家介绍另一种不使用递归的方式,由于没有使用递归,只用到了循环和集合,所以效率更高一些!一、使用递归遍历文件夹整体思路1、使用File封装初始目录,2、打印这个目录3、获取这个目录下所有的子文件和子目录的数组。4、遍历这个数组,取出每个File对象4-1、如果File是否是一个文件,打印4-2、否则就是一个目录,递归调用代码实现publicclassSearchFile{publicstaticvoidmain(String[]args){//初始目录Filedir=newFile("d:/Dev");Datebeg

  9. ES基础入门 - 2

    ES一、简介1、ElasticStackES技术栈:ElasticSearch:存数据+搜索;QL;Kibana:Web可视化平台,分析。LogStash:日志收集,Log4j:产生日志;log.info(xxx)。。。。使用场景:metrics:指标监控…2、基本概念Index(索引)动词:保存(插入)名词:类似MySQL数据库,给数据Type(类型)已废弃,以前类似MySQL的表现在用索引对数据分类Document(文档)真正要保存的一个JSON数据{name:"tcx"}二、入门实战{"name":"DESKTOP-1TSVGKG","cluster_name":"elasticsear

  10. ruby-on-rails - 将字符串转换为 ruby​​-on-rails 中的函数 - 2

    我需要一个通过输入字符串进行计算的方法,像这样function="(a/b)*100"a=25b=50function.something>>50有什么方法吗? 最佳答案 您可以使用instance_eval:function="(a/b)*100"a=25.0b=50instance_evalfunction#=>50.0请注意,使用eval本质上是不安全的,尤其是当您使用外部输入时,因为它可能包含注入(inject)的恶意代码。另请注意,a设置为25.0而不是25,因为如果它是整数a/b将导致0(整数)。

随机推荐