A function is a container for code statements and can be called using the bracketed ()
operator. Parameters can be passed within parentheses when calling so that certain values can be accessed by statements within the function when the function is called.
In the following code, we use the new
operator to create two versions of the addNumbers
function objectone, one using the more common literal mode. Both require two parameters. In each case, we call the function and pass the arguments in brackets to the ()
operator.
Example: sample76.html
<!DOCTYPE html><html lang="en"><body><script> var addNumbersA = new Function('num1', 'num2', 'return num1 + num2'); console.log(addNumbersA(2, 2)); // Logs 4. // Could also be written the literal way, which is much more common. var addNumbersB = function (num1, num2) { return num1 + num2; }; console.log(addNumbersB(2, 2)); // Logs 4. </script></body></html>
Functions can be used to return values, construct objects, or simply serve as a mechanism for running code. JavaScript has many uses for functions, but in their most basic form, functions are the only scope of executable statements.
Function()
ParametersFunction()
The constructor takes an unlimited number of arguments, but the last argument the Function()
constructor expects is a string containing the statements that make up the body of the function. Any arguments passed to the constructor before the last one are available to the function being created. You can also send multiple parameters as comma-separated strings.
In the code below, I contrast the usage of the Function()
constructor with the more common pattern of instantiating function objects.
Example: sample77.html
<!DOCTYPE html><html lang="en"><body><script> var addFunction = new Function('num1', 'num2', 'return num1 + num2'); /* Alternately, a single comma-separated string with arguments can be the first parameter of the constructor, with the function body following. */ var timesFunction = new Function('num1,num2', 'return num1 * num2'); console.log(addFunction(2, 2), timesFunction(2, 2)); // Logs '4 4' // Versus the more common patterns for instantiating a function: var addFunction = function (num1, num2) { return num1 + num2; }; // Expression form. function addFunction(num1, num2) { return num1 + num2; } // Statement form. </script></body></html>
It is not recommended or usually not recommended to directly utilize the Function()
constructor because JavaScript will use eval()
to parse the string containing the function logic. Many people think eval()
is unnecessary overhead. If it is used, there is most likely a flaw in the code design.
Using Function()
constructor without using the new
keyword has the same effect as using only the constructor to create a function object (new Function('x', 'return x')
and function(('x','return x')
).
Call directly Function()
No closure will be created when constructing the function.
Function()
Properties and methodsFunction objects have the following properties (excluding inherited properties and methods):
Properties (Function.prototype;
):
prototype
Function object instances have the following properties and methods (excluding inherited properties and methods):
Instance properties (var myFunction = function(x, y, z) {};
myFunction.length;
):
parameter
Constructor
length
Instance method (var myFunction = function(x, y, z) {};
myFunction.toString();
):
apply()
call()
toString()
While it is possible to create a function that simply executes a code statement, it is also common for the function to return a value. In the following example, we return a string from the sayHi
function.
Example: sample78.html
<!DOCTYPE html><html lang="en"><body><script> var sayHi = function () { return 'Hi'; }; console.log(sayHi()); // Logs "Hi". </script></body></html>
If the function does not specify a return value, it returns undefined
. In the following example, we call the yelp
function, which logs the string "yelp" to the console without explicitly returning a value.
Example: sample79.html
<!DOCTYPE html><html lang="en"><body><script> var yelp = function () { console.log('I am yelping!'); // Functions return undefined even if we don't. } /* Logs true because a value is always returned, even if we don't specifically return one. */ console.log(yelp() === undefined); </script></body></html>
The concept to remember here is that all functions return a value, even if you don't explicitly provide a value to return. If no return value is specified, the return value is undefined
.
In JavaScript, functions are objects. This means that functions can be stored in variables, arrays, or objects. Additionally, functions can be passed to or returned from functions. A function has properties because it is an object. All these factors make functions first-class citizens in JavaScript.
Example: sample80.html
<!DOCTYPE html><html lang="en"><body><script> // Functions can be stored in variables (funcA), arrays (funcB), and objects (funcC). var funcA = function () { }; // Called like so: funcA() var funcB = [function () { } ]; // Called like so: funcB[0]() var funcC = { method: function () { } }; // too.method() or funcC['method']() // Functions can be sent to and sent back from functions. var funcD = function (func) { return func }; var runFuncPassedToFuncD = funcD(function () { console.log('Hi'); }); runFuncPassedToFuncD(); // Functions are objects, which means they can have properties. var funcE = function () { }; funcE.answer = 'yup'; // Instance property. console.log(funcE.answer); // Logs 'yup'. </script></body></html>
It is crucial to realize that a function is an object and therefore a value. It can be passed or enhanced like any other expression in JavaScript.
Parameters are tools for passing values into the function scope when calling a function. In the example below, we call addFunction()
. Since we have predefined it to take two parameters, two additional values are available within its scope.
Example: sample81.html
<!DOCTYPE html><html lang="en"><body><script> var addFunction = function (number1, number2) { var sum = number1 + number2; return sum; } console.log(addFunction(3, 3)); // Logs 6. </script></body></html>
In contrast to some other programming languages, it is perfectly legal to omit parameters in JavaScript, even if the function has been defined to accept these parameters. Missing parameters are only assigned the value undefined
. Of course, if the parameter value is omitted, the function may not work properly.
If you pass unexpected parameters to the function (parameters that were not defined when the function was created), no error will occur. And these arguments can be accessed from the arguments
object, which is available to all functions.
this
和 arguments
值可用于所有函数在所有函数的范围和主体内,this
和 arguments
值可用。
arguments
对象是一个类似数组的对象,包含传递给函数的所有参数。在下面的代码中,即使我们在定义函数时放弃指定参数,我们也可以依赖传递给函数的 arguments
数组来访问在调用时发送的参数。
示例:sample82.html
<!DOCTYPE html><html lang="en"><body><script> var add = function () { return arguments[0] + arguments[1]; }; console.log(add(4, 4)); // Returns 8. </script></body></html>
this
关键字,传递给所有函数,是对包含该函数的对象的引用。正如您所期望的,对象中包含的作为属性(方法)的函数可以使用 this
来获取对父对象的引用。当函数定义在全局作用域时,this
的值为全局对象。查看以下代码并确保您了解 this
返回的内容。
示例:sample83.html
<!DOCTYPE html><html lang="en"><body><script> var myObject1 = { name: 'myObject1', myMethod: function () { console.log(this); } }; myObject1.myMethod(); // Logs 'myObject1'. var myObject2 = function () { console.log(this); }; myObject2(); // Logs window. </script></body></html>
arguments.callee
属性arguments
对象有一个名为 callee
的属性,它是对当前正在执行的函数的引用。此属性可用于从函数范围内引用该函数 (arguments.callee
)a 自引用。在下面的代码中,我们使用此属性来获取对调用函数的引用。
示例:sample84.html
<!DOCTYPE html><html lang="en"><body><script> var foo = function foo() { console.log(arguments.callee); // Logs foo() // callee could be used to invoke recursively the foo function (arguments.callee()) } (); </script></body></html>
当需要递归调用函数时,这非常有用。
length
属性和 arguments.length
arguments
对象具有唯一的 length
属性。虽然您可能认为这个 length 属性将为您提供已定义参数的数量,但它实际上提供了在调用期间发送到函数的参数数量。
示例:sample85.html
<!DOCTYPE html><html lang="en"><body><script> var myFunction = function (z, s, d) { return arguments.length; }; console.log(myFunction()); // Logs 0 because no parameters were passed to the function. </script></body></html>
使用所有 Function()
实例的 length
属性,我们实际上可以获取函数期望的参数总数。
示例:sample86.html
<!DOCTYPE html><html lang="en"><body><script> var myFunction = function (z, s, d, e, r, m, q) { return myFunction.length; }; console.log(myFunction()); // Logs 7. </script></body></html>
arguments.length
属性在 JavaScript 1.4 中已弃用,但可以从函数对象的 length
属性访问发送到函数的参数数量。接下来,您可以通过利用 callee
属性来首先获取对正在调用的函数的引用 (arguments.callee.length
) 来获取长度值。
函数参数可以直接在函数内部重新定义,也可以使用 arguments
数组。看一下这段代码:
示例:sample87.html
<!DOCTYPE html><html lang="en"><body><script> var foo = false; var bar = false; var myFunction = function (foo, bar) { arguments[0] = true; bar = true; console.log(arguments[0], bar); // Logs true true. } myFunction(); </script></body></html>
请注意,我可以使用 arguments
索引或直接为参数重新分配新值来重新定义 bar 参数的值。
通过使用带或不带值的 return
关键字,可以在调用期间随时取消函数。在下面的示例中,如果参数未定义或不是数字,我们将取消 add
函数。
示例:sample88.html
<!DOCTYPE html><html lang="en"><body><script> var add = function (x, y) { // If the parameters are not numbers, return error. if (typeof x !== 'number' || typeof y !== 'number') { return 'pass in numbers'; } return x + y; } console.log(add(3, 3)); // Logs 6. console.log(add('2', '2')); // Logs 'pass in numbers'. </script></body></html>
这里要讲的概念是,您可以在函数执行过程中的任何时刻使用 return
关键字来取消函数的执行。
函数可以用三种不同的方式定义:函数构造函数、函数语句或函数表达式。在下面的示例中,我演示了每种变体。
示例:sample89.html
<!DOCTYPE html><html lang="en"><body><script> /* Function constructor: The last parameter is the function logic, everything before it is a parameter. */ var addConstructor = new Function('x', 'y', 'return x + y'); // Function statement. function addStatement(x, y) { return x + y; } // Function expression. var addExpression = function (x, y) { return x + y; }; console.log(addConstructor(2, 2), addStatement(2, 2), addExpression(2, 2)); // Logs '4 4 4'. </script></body></html>
有人说函数还有第四种类型的定义,称为“命名函数表达式”。命名函数表达式只是一个包含名称的函数表达式(例如, var add = function add(x, y) {return x+y}
)。
call()
和 apply()
)使用四种不同的场景或模式调用函数。
apply()
或 call()
在下面的示例中,我们将检查每种调用模式。
示例:sample90.html
<!DOCTYPE html><html lang="en"><body><script> // Function pattern. var myFunction = function () { return 'foo' }; console.log(myFunction()); // Logs 'foo'. // Method pattern. var myObject = { myFunction: function () { return 'bar'; } } console.log(myObject.myFunction()); // Logs 'bar'. // Constructor pattern. var Cody = function () { this.living = true; this.age = 33; this.gender = 'male'; this.getGender = function () { return this.gender; }; } var cody = new Cody(); // Invoke via the Cody constructor. console.log(cody); // Logs the cody object and properties. // apply() and call() pattern. var greet = { runGreet: function () { console.log(this.name, arguments[0], arguments[1]); } } var cody = { name: 'cody' }; var lisa = { name: 'lisa' }; // Invoke the runGreet function as if it were inside of the cody object. greet.runGreet.call(cody, 'foo', 'bar'); // Logs 'cody foo bar'. // Invoke the runGreet function as if it were inside of the lisa object. greet.runGreet.apply(lisa, ['foo', 'bar']); // Logs 'lisa foo bar'. /* Notice the difference between call() and apply() in how parameters are sent to the function being invoked. */ </script></body></html>
确保您了解所有四种调用模式,因为您将遇到的代码可能包含其中任何一种。
匿名函数是没有给出标识符的函数。匿名函数主要用于将函数作为参数传递给另一个函数。
示例:sample91.html
<!DOCTYPE html><html lang="en"><body><script> // function(){console.log('hi');}; // Anonymous function, but no way to invoke it. // Create a function that can invoke our anonymous function. var sayHi = function (f) { f(); // Invoke the anonymous function. } // Pass an anonymous function as a parameter. sayHi(function () { console.log('hi'); }); // Logs 'hi'. </script></body></html>
函数表达式(实际上是除从 Function()
构造函数创建的函数之外的任何函数)可以在定义后使用括号运算符立即调用。在以下示例中,我们创建 sayWord()
函数表达式,然后立即调用该函数。这被认为是一个自调用函数。
示例:sample92.html
<!DOCTYPE html><html lang="en"><body><script> var sayWord = function () { console.log('Word 2 yo mo!'); } (); // Logs 'Word 2 yo mo!' </script></body></html>
可以创建自调用的匿名函数语句。这称为自调用匿名函数。在下面的示例中,我们创建了几个立即调用的匿名函数。
示例:sample93.html
<!DOCTYPE html><html lang="en"><body><script> // Most commonly used/seen in the wild. (function (msg) { console.log(msg); })('Hi'); // Slightly different, but achieving the same thing: (function (msg) { console.log(msg) } ('Hi')); // The shortest possible solution. !function sayHi(msg) { console.log(msg); } ('Hi'); // FYI, this does NOT work! // function sayHi() {console.log('hi');}(); </script></body></html>
根据 ECMAScript 标准,如果要立即调用函数,则需要在函数两边加上括号(或将函数转换为表达式的任何内容)。
函数可以无限期地嵌套在其他函数中。在下面的代码示例中,我们将 goo
函数封装在 bar
函数内部,该函数位于 foo
函数内部。
示例:sample94.html
<!DOCTYPE html><html lang="en"><body><script> var foo = function () { var bar = function () { var goo = function () { console.log(this); // Logs reference to head window object. } (); } (); } (); </script></body></html>
这里的简单概念是函数可以嵌套,并且嵌套的深度没有限制。
请记住,嵌套函数的 this
的值将是 JavaScript 1.5、ECMA-262 第 3 版中的头对象(Web 浏览器中的 window
对象)。
如前所述,函数是 JavaScript 中的一等公民。由于函数是一个值,并且函数可以传递任何类型的值,因此函数可以传递给函数。接受和/或返回其他函数的函数有时称为“高阶函数”。
在下面的代码中,我们将一个匿名函数传递给 foo
函数,然后立即从 foo
函数返回。变量 bar
所指向的正是这个匿名函数,因为 foo
接受并返回匿名函数。
示例:sample95.html
<!DOCTYPE html><html lang="en"><body><script> // Functions can be sent to, and sent back from, functions. var foo = function (f) { return f; } var bar = foo(function () { console.log('Hi'); }); bar(); // Logs 'Hi'. </script></body></html>
因此,当调用 bar
时,它会调用传递给 foo()
函数的匿名函数,然后从 foo()
函数传回并从 bar
引用多变的。所有这些都是为了展示函数可以像任何其他值一样传递的事实。
函数语句可以在执行期间在其实际定义之前调用。这有点奇怪,但您应该意识到这一点,以便您可以利用它,或者至少知道当您遇到它时会发生什么。在下面的示例中,我在定义 sayYo()
和 sum()
函数语句之前调用它们。
示例:sample96.html
<!DOCTYPE html><html lang="en"><body><script> // Example 1 var speak = function () { sayYo(); // sayYo() has not been defined yet, but it can still be invoked, logs 'yo'. function sayYo() { console.log('Yo'); } } (); // Invoke // Example 2 console.log(sum(2, 2)); // Invoke sum(), which is not defined yet, but can still be invoked. function sum(x, y) { return x + y; } </script></body></html>
发生这种情况是因为在代码运行之前,函数语句被解释并添加到执行堆栈/上下文中。确保您在使用函数语句时意识到这一点。
定义为函数表达式的函数不会被提升。仅提升函数语句。
函数调用自身是完全合法的。事实上,这经常被用在众所周知的编码模式中。在下面的代码中,我们启动 countDownFrom
函数,然后该函数通过函数名称 countDownFrom
调用自身。本质上,这会创建一个从 5 倒数到 0 的循环。
示例:sample97.html
<!DOCTYPE html><html lang="en"><body><script> var countDownFrom = function countDownFrom(num) { console.log(num); num--; // Change the parameter value. if (num < 0) { return false; } // If num < 0 return function with no recursion. // Could have also done arguments.callee(num) if it was an anonymous function. countDownFrom(num); }; countDownFrom(5); // Kick off the function, which logs separately 5, 4, 3, 2, 1, 0. </script></body></html>
您应该意识到,函数调用自身(也称为递归)或重复执行此操作是很自然的。
函数是 JavaScript 最常用的方面之一,希望您现在对如何使用它们有了更好的了解。
The above is the detailed content of function() that implements the function. For more information, please follow other related articles on the PHP Chinese website!