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




page javascript函数未定义 js函数未定义怎么办_子过程或函数未定义

图片来源:Unsplash/Luca Bravo



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

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

1. 函数声明

2. 函数表达式

3. 生成器函数




page javascript函数未定义 js函数未定义怎么办_函数表达式_02


1. 函数声明

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

function name (parameter){ statements }

函数声明语句

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

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

首先,看一个简单实例:

function hello(name){console.log("Hello "+ name)}hello('stuti')// Hello stutihello(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()) // undefinedfunction notSomething(){ return 1}console.log(notSomething()) // 1

函数声明中提升是什么?

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

观察下方实例:

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

函数声明中的提升

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


page javascript函数未定义 js函数未定义怎么办_函数表达式_02


2. 函数表达式


page javascript函数未定义 js函数未定义怎么办_函数表达式_04

图片来源: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 definedlet myName =function () { console.log(`My name is Stuti Chauhan`)}

函数表达式中无提升

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

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

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

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


page javascript函数未定义 js函数未定义怎么办_函数表达式_02


3. 生成器函数


page javascript函数未定义 js函数未定义怎么办_生成器_06

图片来源: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 pauseconsole.log(gen.next().value); // printed after the pause // end of the functionconsole.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