当前位置: 首页 > 文档资料 > ES6 入门教程 >

功能(Functions)

优质
小牛编辑
130浏览
2023-12-01

Functions是可读,可维护和可重用代码的构建块。 使用function关键字定义函数。 以下是定义标准函数的语法。

function function_name() { 
   // function body 
} 

要强制执行该函数,必须调用它。 这称为函数调用。 以下是调用函数的语法。

function_name()

示例:简单的函数定义

//define a  function 
function test() { 
   console.log("function called") 
} 
//call the function 
test()

该示例定义了函数test()。 一对分隔符({})定义函数体。 它也被称为function scope 。 必须调用函数来强制执行。

成功执行上述代码后,将显示以下输出。

function called

函数的分类 (Classification of Functions)

功能可以分类为ReturningParameterized功能。

Returning Functions

函数也可以将值与控制一起返回给调用者。 这些函数称为返回函数。

以下是返回函数的语法。

function function_name() { 
   //statements 
   return value; 
}
  • 返回函数必须以return语句结束。

  • 函数最多可以返回一个值。 换句话说,每个函数只能有一个return语句。

  • return语句应该是函数中的最后一个语句。

以下代码片段是返回函数的示例 -

function retStr() { 
   return "hello world!!!" 
}  
var val = retStr() 
console.log(val) 

上面的示例定义了一个函数,该函数将字符串“hello world !!!”返回给调用者。 成功执行上述代码后,将显示以下输出。

hello world!!! 

参数化功能 (Parameterized Functions)

参数是一种将值传递给函数的机制。 参数构成函数签名的一部分。 参数值在调用期间传递给函数。 除非明确指定,否则传递给函数的值的数量必须与定义的参数数量相匹配。

以下是定义参数化函数的语法。

function func_name( param1,param2 ,…..paramN) {   
   ...... 
   ...... 
}

Example − Parameterized Function

该示例定义了一个函数add,它接受两个参数n1n2并打印它们的和。 调用时,参数值将传递给函数。

function add( n1,n2) { 
   var sum = n1 + n2 
   console.log("The sum of the values entered "+sum) 
} 
add(12,13) 

成功执行上述代码后,将显示以下输出。

The sum of the values entered 25

默认功能参数

在ES6中,如果没有传递任何值或未定义参数,则函数允许使用默认值初始化参数。 以下代码说明了相同的内容。

function add(a, b = 1) { 
   return a+b; 
} 
console.log(add(4))

上面的函数默认将b的值设置为1。 除非明确传递了值,否则该函数将始终将参数b视为值1。 成功执行上述代码后,将显示以下输出。

5

如果函数显式传递值,则将覆盖参数的默认值。

function add(a, b = 1) { 
   return a + b; 
} 
console.log(add(4,2))

上面的代码将参数b的值显式设置为2,从而覆盖其默认值。 成功执行上述代码后,将显示以下输出。

6

休息参数

Rest参数类似于Java中的变量参数。 Rest参数不限制可以传递给函数的值的数量。 但是,传递的值必须都是相同的类型。 换句话说,rest参数充当相同类型的多个参数的占位符。

要声明rest参数,参数名称前缀为三个句点,称为spread运算符。 以下示例说明了相同的内容。

function fun1(...params) { 
   console.log(params.length); 
}  
fun1();  
fun1(5); 
fun1(5, 6, 7); 

成功执行上述代码后,将显示以下输出。

0 
1 
3

Note - Rest参数应该是函数参数列表中的最后一个。

匿名函数

未绑定到标识符(函数名称)的函数称为匿名函数。 这些函数在运行时动态声明。 匿名函数可以接受输入和返回输出,就像标准函数一样。 匿名函数在初始创建后通常无法访问。

可以为变量分配匿名函数。 这种表达式称为function expression

以下是匿名函数的语法。

var res = function( [arguments] ) { ... } 

Example − Anonymous Function

var f = function(){ return "hello"} 
console.log(f()) 

成功执行上述代码后,将显示以下输出。

hello 

Example − Anonymous Parameterized Function

var func = function(x,y){ return x*y }; 
function product() { 
   var result; 
   result = func(10,20); 
   console.log("The product : "+result) 
} 
product()

成功执行上述代码后,将显示以下输出。

The product : 200 

函数构造函数

函数语句不是定义新函数的唯一方法; 您可以使用Function()构造函数和new运算符动态定义函数。

以下是使用Function()构造函数和new运算符创建函数的语法。

var variablename = new Function(Arg1, Arg2..., "Function Body"); 

Function()构造函数需要任意数量的字符串参数。 最后一个参数是函数体 - 它可以包含任意JavaScript语句,用分号相互分隔。

Function()构造函数不传递任何指定其创建的函数名称的参数。

Example − Function Constructor

var func = new Function("x", "y", "return x*y;"); 
function product() { 
   var result; 
   result = func(10,20); 
   console.log("The product : "+result)
} 
product()

在上面的示例中,Function()构造函数用于定义匿名函数。 该函数接受两个参数并返回其产品。

成功执行上述代码后,将显示以下输出。

The product : 200

递归和JavaScript函数 (Recursion and JavaScript Functions)

递归是一种通过使函数自身重复调用直到它到达结果来迭代操作的技术。 当您需要使用循环内的不同参数重复调用相同的函数时,最好应用递归。

Example − Recursion

function factorial(num) { 
   if(num<=0) { 
      return 1; 
   } else { 
      return (num * factorial(num-1)  ) 
   } 
} 
console.log(factorial(6)) 

在上面的例子中,函数调用自身。 成功执行上述代码后,将显示以下输出。

720 

Example − Anonymous Recursive Function

(function() { 
   var msg = "Hello World" 
   console.log(msg)
})()

该函数使用一对括号()调用自身。 成功执行上述代码后,将显示以下输出。

Hello World 

Lambda 函数

Lambda是指编程中的匿名函数。 Lambda函数是表示匿名函数的简明机制。 这些函数也称为Arrow functions

Lambda函数 - 解剖学

Lambda函数有3个部分 -

  • Parameters - 函数可以选择具有参数。

  • fat arrow notation/lambda notation (=“):它也被称为转到运算符。

  • Statements - 表示函数的指令集。

Tip - 按照惯例,鼓励使用单个字母参数来实现紧凑和精确的函数声明。

Lambda表达

它是一个匿名函数表达式,指向一行代码。 以下是相同的语法。

([param1, parma2,…param n] )=>statement;

Example − Lambda Expression

var foo = (x)=>10+x 
console.log(foo(10)) 

Example声明了一个lambda表达式函数。 该函数返回10的总和和传递的参数。

成功执行上述代码后,将显示以下输出。

20

Lambda 语句

它是一个匿名函数声明,指向一个代码块。 当函数体跨越多行时使用此语法。 以下是相同的语法。

( [param1, parma2,…param n] )=> {       
   //code block 
}

Example − Lambda Statement

var msg = ()=> { 
   console.log("function invoked") 
} 
msg() 

返回函数的引用并将其存储在变量msg中。 成功执行上述代码后,将显示以下输出。

function  invoked 

句法变异

单个参数的可选括号。

var msg = x=> { 
   console.log(x) 
} 
msg(10)

单个语句的可选括号。 没有参数的空括号。

var disp = ()=>console.log("Hello World") 
disp();

功能表达和功能声明

函数表达式和函数声明不是同义词。 与函数表达式不同,函数声明由函数名绑定。

两者之间的根本区别在于,函数声明在执行之前被解析。 另一方面,仅在脚本引擎在执行期间遇到函数表达式时才解析函数表达式。

当JavaScript解析器在主代码流中看到一个函数时,它会假定函数声明。 当函数作为语句的一部分出现时,它是一个函数表达式。

功能Hoisting

与变量一样,函数也可以悬挂。 与变量不同,函数声明在提升时,提升函数定义而不是仅仅提升函数的名称。

以下代码片段说明了JavaScript中的函数提升。

hoist_function();  
function hoist_function() { 
   console.log("foo"); 
} 

成功执行上述代码后,将显示以下输出。

foo 

但是,函数表达式不能被提升。 以下代码段说明了相同的内容。

hoist_function(); // TypeError: hoist_function() is not a function  
var hoist_function() = function() { 
   console.log("bar"); 
};

立即调用函数表达式

立即调用函数表达式(IIFE)可用于避免块内的可变提升。 它允许公共访问方法,同时保留函数中定义的变量的隐私。 此模式称为自执行匿名函数。 以下两个例子更好地解释了这个概念。

实施例1:IIFE

var main = function() { 
   var loop = function() { 
      for(var x = 0;x<5;x++) {
         console.log(x); 
      } 
   }(); 
   console.log("x can not be accessed outside the block scope x value is :"+x); 
} 
main();

实施例2:IIFE

var main = function() { 
   (function() { 
      for(var x = 0;x<5;x++) { 
         console.log(x); 
      } 
   })(); 
   console.log("x can not be accessed outside the block scope x value is :"+x); 
} 
main();

两个示例都将呈现以下输出。

0 
1 
2 
3 
4 
Uncaught ReferenceError: x is not define

生成器函数 (Generator Functions)

当调用普通函数时,控件依赖于被调用的函数,直到它返回为止。 使用ES6中的生成器,调用函数现在可以控制被调用函数的执行。 发电机就像一个常规功能,除了 -

  • 该函数可以在任何时候将控制权交还给调用者。

  • 当您调用生成器时,它不会立即运行。 相反,你得到一个迭代器。 该函数在调用迭代器的下一个方法时运行。

生成器用函数关键字后缀用星号表示; 否则,它们的语法与常规函数相同。

以下示例说明了相同的内容。

"use strict" 
function* rainbow() { 
   // the asterisk marks this as a generator 
   yield 'red'; 
   yield 'orange'; 
   yield 'yellow'; 
   yield 'green'; 
   yield 'blue'; 
   yield 'indigo'; 
   yield 'violet'; 
} 
for(let color of rainbow()) { 
   console.log(color); 
} 

生成器启用调用者和被调用函数之间的双向通信。 这是通过使用yield关键字完成的。

考虑以下示例 -

function* ask() { 
   const name = yield "What is your name?"; 
   const sport = yield "What is your favorite sport?"; 
   return `${name}'s favorite sport is ${sport}`; 
}  
const it = ask(); 
console.log(it.next()); 
console.log(it.next('Ethan'));  
console.log(it.next('Cricket')); 

发电机功能的顺序如下 -

  • 发电机暂停开始; 迭代器被返回。

  • it.next()产生“你叫什么名字”。 发电机暂停。 这是由yield关键字完成的。

  • 调用it.next(“Ethan”)将值Ethan分配给变量名称并产生“你最喜欢的运动是什么?”同样,生成器暂停。

  • 调用it.next(“Cricket”)将值Cricket赋值给变量sport并执行后续的return语句。

因此,上述代码的输出将是 -

{ 
   value: 'What is your name?', done: false 
} 
{ 
   value: 'What is your favorite sport?', done: false 
} 
{ 
   value: 'Ethan\'s favorite sport is Cricket', done: true 
}

Note - 无法使用箭头函数表示生成器函数。