関数を実装する function()

WBOY
WBOYオリジナル
2023-09-04 09:41:201260ブラウズ

関数を実装する function()

関数はコード ステートメントのコンテナであり、括弧で囲まれた () 演算子を使用して呼び出すことができます。関数の呼び出し時に関数内のステートメントによって特定の値にアクセスできるように、呼び出し時にパラメーターをかっこ内で渡すことができます。

次のコードでは、new 演算子を使用して addNumbers 関数 objectone の 2 つのバージョンを作成します。1 つはより一般的なリテラル モードを使用します。どちらも 2 つのパラメータが必要です。いずれの場合も、関数を呼び出し、括弧内の引数を () 演算子に渡します。

例:sample76.html

リーリー

関数は、値を返したり、オブジェクトを構築したり、単にコードを実行するメカニズムとして機能したりするために使用できます。 JavaScript では関数をさまざまに使用できますが、最も基本的な形式では、関数は実行可能ステートメントの唯一のスコープです。


関数() パラメータ

Function() コンストラクターは無制限の数の引数を受け取りますが、Function() コンストラクターが期待する最後の引数は、本体を構成するステートメントを含む文字列です。関数。最後の引数より前にコンストラクターに渡された引数は、作成中の関数で使用できます。複数のパラメータをカンマ区切りの文字列として送信することもできます。

以下のコードでは、Function() コンストラクターの使用法を、関数オブジェクトをインスタンス化するより一般的なパターンと対比しています。

例:sample77.html

リーリー

JavaScript は eval() を使用して関数ロジックを含む文字列を解析するため、Function() コンストラクターを直接利用することは推奨されません。また、通常は推奨されません。多くの人は、eval() は不必要なオーバーヘッドだと考えています。使用されている場合は、コード設計に欠陥がある可能性が高くなります。

new キーワードを使用せずに Function() コンストラクターを使用すると、コンストラクターのみを使用して関数オブジェクト (new Function('x', 'return x') および function(('x','return x')).

直接呼び出す Function() 関数の構築時にクロージャは作成されません。


Function() プロパティとメソッド

関数オブジェクトには次のプロパティがあります (継承されたプロパティとメソッドを除く):

プロパティ (Function.prototype;):

    ######プロトタイプ######
  • 関数オブジェクトのインスタンスのプロパティとメソッド
関数オブジェクトのインスタンスには、次のプロパティとメソッドがあります (継承されたプロパティとメソッドを除く)。
インスタンス プロパティ (

var myFunction = function(x, y, z) {};

myFunction.length;

):

パラメータ

######コンストラクタ###### ######長さ######
  • インスタンス メソッド (var myFunction = function(x, y, z) {};
  • myFunction.toString();
  • ): ######適用する()###### ######電話()######
  • toString()

関数は常に値を返します コード ステートメントを単に実行する関数を作成することもできますが、関数が値を返すことも一般的です。次の例では、sayHi 関数から文字列を返します。

    例:sample78.html
  • リーリー 関数で戻り値が指定されていない場合、unknown
  • が返されます。次の例では、
  • yelp 関数を呼び出します。この関数は、値を明示的に返さずに、文字列「yelp」をコンソールに記録します。
  • 例:sample79.html
  • リーリー ここで覚えておくべき概念は、返す値を明示的に指定しなくても、すべての関数は値を返すということです。戻り値が指定されていない場合、戻り値は undefine
  • になります。

関数は第一級市民です (構文だけでなく値も)

JavaScript では、関数はオブジェクトです。これは、関数を変数、配列、またはオブジェクトに格納できることを意味します。さらに、関数を関数に渡したり、関数から返したりすることができます。関数はオブジェクトであるため、プロパティを持ちます。これらすべての要素により、関数は JavaScript の第一級市民となります。 例:sample80.html

リーリー

関数はオブジェクトであり、したがって値であることを理解することが重要です。 JavaScript の他の式と同様に、渡したり拡張したりできます。

パラメータを関数に渡す パラメータは、関数を呼び出すときに関数スコープに値を渡すためのツールです。以下の例では、addFunction()

を呼び出します。 2 つのパラメーターを取るように事前定義しているため、そのスコープ内で 2 つの追加の値を使用できます。

例:sample81.html

リーリー 他のプログラミング言語とは対照的に、JavaScript では、パラメーターを受け入れるように関数が定義されている場合でも、パラメーターを省略することは完全に合法です。欠落しているパラメータには、値 未定義

が割り当てられるだけです。もちろん、パラメータの値を省略すると、機能が正しく動作しない可能性があります。

予期しないパラメータ (関数の作成時に定義されていなかったパラメータ) を関数に渡しても、エラーは発生しません。これらの引数は、すべての関数で使用できる

arguments

オブジェクトからアクセスできます。


thisarguments 值可用于所有函数

在所有函数的范围和主体内,thisarguments 值可用。

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 最常用的方面之一,希望您现在对如何使用它们有了更好的了解。

以上が関数を実装する function()の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。