定义函数的三种种方法(常见的定义函数的方法)

全文共2416字,预计学习时长5分钟

定义函数的三种种方法(常见的定义函数的方法)

图片来源:Unsplash/Luca Bravo

函数是编程中的关键部件之一。这些函数可执行特定任务,并可反复调用执行。将Javascript中的函数和其他编程语言中的函数相比较,其中最大的区别在于Javascript函数为一级对象,这意味着Javascript中的函数表现类似于对象,可作为变量、数组和其他对象。

 

本文就定义函数的三种不同方法进行讨论:

1. 函数声明

2. 函数表达式

3. 生成器函数

定义函数的三种种方法(常见的定义函数的方法)

 

1. 函数声明

 

函数声明可能是最常见的方式了。观察如下语句:

function name (parameter)
{
 statements 
}

 

函数声明语句

函数由关键字函数、函数的强制名称和括号内的参数组成(定义函数也可无参数)。最后,大括号内则是函数的主体,用以执行实际任务。

 

理解形参和实参的区别很重要。形参是定义函数时的一个变量。在调用函数时,实参则是输入函数形参的实际数据。

 

首先,看一个简单实例:

function hello(name)
{
console.log("Hello "+ name)
}
hello('stuti')
// Hello stuti
hello(12)
// Hello 12

 

名为hello的函数以实际参数名称声明,在控制台记录消息。从本例中,可以看出,因为实际参数上无指定类型,所以其既适用于string函数,也适用于number函数。倘若只是希望该函数是一个名称而不是数值呢?很遗憾,由于Javascript中没有预建法来实现这一点,必须手动确定输入函数的实际参数类型,如下所示:

 

function hello(name) {
 if (typeof name === 'string')
 console.log("Hello " + name)
 else
 console.log("Please input a Name")
}
hello(12) 
// Plese input a Name

 

默认情况下,函数返回未定义变量。若要返回任何其他值,则函数必须具备返回语句,而由该语句指定返回值。

 

function something(){
}
console.log(something()) // undefined
function notSomething(){
 return 1
}
console.log(notSomething()) // 1

 

函数声明中提升是什么?

 

简单地说,这意味着在执行代码时,无论何处声明函数或变量,它们均会移动至作用域的顶部。这也就是所谓的提升。

 

观察下方实例:

myName()
// My name is Stuti Chahuhan
function myName() {
 console.log(`My name is Stuti Chauhan`)
}

 

函数声明中的提升

此处甚至是在声明之前就调用了这个函数——提升。

 

定义函数的三种种方法(常见的定义函数的方法)

 

2. 函数表达式

定义函数的三种种方法(常见的定义函数的方法)

图片来源:unsplash.com/@creativegangsters

函数表达式与函数声明极为相似,连语句都不甚相同。最主要的区别在于函数表达式不以关键字函数开头,且函数名称可选,在此情况下,该函数表达式则可以成为一个匿名函数。如果函数有名称,则将其称为命名函数表达式。

let checkNumber = function check (num){
 return (num %2==0)?"even" : "odd"
 }
console.log(checkNumber(50)) 
// even

 

函数表达式的例子

现在来观察一下定义上述函数的匿名法。

//Anonymous Function 
let checkNumber = function (num){
 return (num %2==0)?"even" : "odd"
 }
console.log(checkNumber(50)) 
// even

 

匿名函数表达式

函数声明和函数表达式最关键的区别就在于函数表达式无提升功能。若在函数表达式中尝试与提升函数声明相同的项目,则会出现报错。

myName()
// ReferenceError: myName is not defined
let myName =function () {
 console.log(`My name is Stuti Chauhan`)
}

 

函数表达式中无提升

IIFE(立即执行函数表达式)

 

这意味着函数一旦定义就开始运行,而函数表达式附在分组操作符()中,

( function () {
 let num = 4
 return num
 })
//4

 

为什么典型的函数表达式需要IIFE?一般定义一个函数,随后多次调用。但倘若只想调用一次用来生成输出,并且不再使用该函数呢?由此就出现了IIFE。该函数会立即执行,并在以后不再经程序访问。因为不需再调用该函数,所以它也不需要名称,因此匿名函数表达式首选IIFE。

定义函数的三种种方法(常见的定义函数的方法)

3. 生成器函数

定义函数的三种种方法(常见的定义函数的方法)

图片来源:unsplash.com/@roman_lazygeek

普通函数遵循运行-完成的模型,不能在执行最后一行之前停止运行。若想在执行过程中退出,必须返回或抛出一个错误。

 

而生成器函数可以在执行过程中停止。当其调回时,仍然从停止的地方继续。

 

该函数与普通函数一样进行声明,但不同之处在于生成器函数在function关键字后面带有星号*,其间可包含任意数量的空格。

 

还有一点需要注意:在JavaScript中,生成器是一个函数,该函数返回一个对象,在该对象上可调用next(),每次调用next()都会返回一个结构如下的对象:

{ 
 value: Any,
 done: true|false
} 

 

此对象包含两个属性:value和done。Value是对象的实际值,而done规定了函数终止的属性——默认值为false,当其变为true时,则函数停止。

 

通过一个简单的例子来理解这点:

function * generatorFunction()
{ 
 console.log('first to execute');
 yield 'takes a pause'; 
 
 console.log(' printed after the pause'); 
 yield 'end of the function';
 
}
const gen = generatorFunction();
console.log(gen.next().value); // first to execute
 // takes a pause
console.log(gen.next().value); // printed after the pause
 // end of the function
console.log(gen.next().value); 
 // undefined

 

函数本体中,不使用return关键字——而是使用yeild,如果使用了return,则会将done属性更改为true,函数将结束——之后的任何操作都不会执行。Yield给出为其分配的值。

 

首先,在调用函数前先定义函数,同时调用一个生成器函数,形成一个生成器对象,存储在变量中。

 

然后在使用next()和value属性时调用对象。第一次使用next()时,函数执行开始。首先,运行console.log (“首次执行”)并将其记录在控制台中,然后遇到yield—输出 “暂停”值,执行停止。

 

第二次调用next()时,它从上次暂停处继续。同样,首先运行console.log(),再次遇到yield,生成“函数结束”值,函数停止。

 

第三次调用next()时,结果是未定义。这是因为由生成器函数生成的对象只能迭代一次——该对象现在是无用的,必须生成一个新对象才能重新启动程序。

function* generator() {
 yield "some value";
 return "ends here";
 yield "will never execute";
 yield "never reach here"
}
var gen = generator()
console.log(gen.next()); 
// { value: "some value", done: false }
console.log(gen.next()); 
// { value: "ends here", done: true }
console.log(gen.next()); 
// { value: undefined, done: true }
console.log(gen.next()); 
// { value: undefined, done: true }

 

如果使用return而不是yield,那么数据的值就会被更改为true,之后就不会执行任何操作。与Promise结合使用时,就异步编程而言,生成器是一个非常强大的工具。该函数即使不能完全消除回调的问题,也可以减轻其问题的程度。

 

定义函数的三种种方法(常见的定义函数的方法)

结论:哪种方法更好?

 

事实上,我们不能将其进行比较,然后说一个比另一个好——声明的类型还是取决于具体情况或条件。

 

为实现更好的异步功能则使用生成器函数,针对立即执行函数的情况,则使用匿名函数表达式。

定义函数的三种种方法(常见的定义函数的方法)

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发表评论

登录后才能评论