質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

5回答

6983閲覧

javascriptで同じ名前で複数の関数

uer03108

総合スコア194

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2017/11/18 07:59

javascriptで下記の様な事は出来るでしょうか。
名前が同じで、引数の数が違う関数です。

javascript

1//合計の計算 2function calcSum(n1, n2){ 3 return n1 + n2; 4} 5 6//合計の計算 7function calcSum(n1, n2, n3){ 8 return n1 + n2 + n3; 9} 10

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答5

0

ベストアンサー

残念ながら、JavaScriptで同じ名前の関数を複数宣言することはできません。

ただ、いくつか代替となる手段はあります。

javascript

1// 引数の個数を見分ける 2// 引数の個数で違う動きをする場合におすすめ 3function calcSum1(n1, n2, n3) { 4 if(arguments.length === 2) { 5 // 2個の場合の処理 6 } 7 if(arguments.length === 3) { 8 // 3個の場合の処理 9 } 10} 11 12// 「引数全部処理したい場合」、以下2つのような手もある 13function calcSum2() { 14 var ret = 0; 15 for(var i = 0; i < arguments.length; i++) { 16 ret += arguments[i]; 17 } 18 return ret; 19} 20 21// ES6(現状では環境を選ぶ) 22function calcSum3(...args) { 23 // argsは本物の配列 24 return args.reduce((total, current) => total + current, 0); 25}

投稿2017/11/18 08:06

maisumakun

総合スコア145184

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

uer03108

2017/11/18 09:00

ご回答有難うございました。 argumentsを利用すると引数を宣言する必要性が薄れるように感じました。 勿論、宣言しておいた方が可読性は高まると思いますが。
maisumakun

2017/11/18 09:10

babelやNode前提の環境では、(同種の引数を任意個受ける、という状況なら)最後のようにspread引数として宣言しておくのがわかりやすい気もします。
guest

0

他回答者の方がもう色々な方法を提示されたので、
私は選択肢の使い分けの目安を示したいと思います。


ご質問のサンプルコードのように、
増えていく引数のが同じで、処理も同じ、単調な変化の場合は、
配列を引数に取ってループの回数を変えるのが一番シンプルです。

次に、引数が2個だと引き算、3個だと足し算、
のように型は同じでも処理を分ける必要がある場合、
IF文を使って分岐させます。

さらに、数を足すのか、文字列を連結するのか、
という風に引数の型が異なる場合、
別のオブジェクトに同名のメソッドを付ける
(ポリモーフィズム)のがオススメです。

なぜかというと、型が違う場合、別系統のデータだから、
別オブジェクトに分けた方が整理しやすいのです。
とくにIF文がネストするような複雑な場合に威力を発揮します。


なお、方向性は違いますが、引数のパターンが単調な場合、
とくに内部のIF文を分けるためのフラグとして引数を使っている場合、
高階関数と部分適用で分ける関数型的な手法も有力です。

この場合、名前を増やす代わりに、引数を減らして整理します。
同名はひとつの手段で、目的はコードの整理だと思うので、選択肢のひとつです。

投稿2017/11/18 09:55

編集2017/11/18 09:58
LLman

総合スコア5592

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

uer03108

2017/11/26 07:13

回答有難うございます。 高階関数はjavascript特有ですね。 使い方が分かれば便利だと思います。 引数に規則性があれば、その部分は簡易化できそうですね。
guest

0

別オブジェクトのメソッドにするとか。

JavaScript

1var a = {}; 2var b = {}; 3a.calcSum = function ( n1, n2 ) { 4 return n1 + n2; 5} 6b.calcSum = function ( n1, n2, n3 ) { 7 return n1 + n2 + n3; 8} 9console.log( a.calcSum( 1, 2 ) ); 10console.log( b.calcSum( 1, 2, 3 ) );

投稿2017/11/18 08:14

kei344

総合スコア69407

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

uer03108

2017/11/18 09:04

ご回答有難うございました。 console.log(s2.calcSum(n1, n2)); console.log(s3.calcSum(n1, n2, n3)); などと書くと分かり易そうですね。 また、別オブジェクト(クラス)で同じ関数名の処理を行うことはありそうですね。
miyabi-sun

2017/11/18 09:57

あー…なるほど! ポリモーフィズムの話だったんですね。 そう考えれば良い解決方法の一つですね。
guest

0

多重定義

JavaScriptに多重定義の仕組みはない為、可変引数コード実装時に使われる機構を活用することになります。
多重定義と同様に関数を分割定義したいのならば、多重定義用の関数を一つ用意してやる必要があります。

JavaScript

1function calcSum (n1) { 2 switch(arguments.length) { 3 case 0: 4 throw new Error; 5 case 1: 6 return n1; 7 case 2: 8 return calcSum2(n1, arguments[0]); 9 case 3: 10 return calcSum3(n1, arguments[0], arguments[1]); 11 } 12 13 throw new Error; 14} 15 16function calcSum2 (n1, n2){ 17 return n1 + n2; 18} 19 20function calcSum3 (n1, n2, n3){ 21 return n1 + n2 + n3; 22} 23 24console.log(calcSum(1)); // 1 25console.log(calcSum(1, 2)); // 2 26console.log(calcSum(1, 2, 3)); // 4 27console.log(calcSum(1, 2, 3, 4)); // Error 28console.log(calcSum()); // Error

ここで重要なのは、

JavaScript

1calcSum.length === 1; // true

であり、最低一つの引数を要求する事が明確になっている点です。
arguments を使って実引数を参照する事で、 Function#length の値をコントロール出来ます。

なお、ES6 の Rest parameters で同様の実装をするには、次のように書きます。

JavaScript

1function calcSum (n1, ...n) {} 2console.log(calcSum.length); // 1

Re: uer03108 さん

投稿2017/11/18 14:10

編集2017/11/18 14:36
think49

総合スコア18164

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

uer03108

2017/11/20 02:45

ご回答有難うございました。 必須の引数を関数で定義しておいて、オプション的なものはargumentsで取得すれば、分かり易そうですね。 vbaでもそうなってたな。
guest

0

JavaScriptでは同名の関数は1個しか存在出来ません。

関数を定義すると、関数の内部でarguments変数が利用可能になります。
それでよしなに計算し、if文等で処理を分岐させる仕組みを盛り込むことになります。
参考サイト: arguments - MDN

他にも引数が不足していても、余った引数にUndefinedが格納されるだけでエラーにはなりません。

JavaScript

1function calcSum(a, b, c) { 2 return a + b + c; 3} 4console.log(calcSum(1, 2, 3)); // 6 5console.log(calcSum(1, 2)); // NaN <- ちくしょう! 6 7function calcSum(a, b, c) { 8 a = a || 0; 9 b = b || 0; 10 c = c || 0; 11 return a + b + c; 12} 13console.log(calcSum(1, 2, 3)); // 6 14console.log(calcSum(1, 2)); // 3 15 16// ES2015という新しい書き方では、引数の初期値が宣言出来るようになりました。 17function calcSum(a = 0, b = 0, c = 0) { 18 return a + b + c; 19} 20console.log(calcSum(1, 2)); // 3

おまけ: 単純操作なら配列操作

calcSumというのは複数の数値を全て足すという処理ですね?
例題なんでアレですが、こういう単純処理ならば配列操作でいけますね。
配列を受け取る関数を作って対応できます。

JavaScript

1function calcSum(nums) { 2 return nums.reduce(function(a, b){return a + b}, 0); 3} 4console.log(calcSum([])); // 0 5console.log(calcSum([1])); // 1 6console.log(calcSum([1, 2])); // 3 7console.log(calcSum([1, 2, 3])); // 6 8console.log(calcSum([1, 2, 3, 5, 5])); // 16

argumentsと配列操作を使ってかっこよく仕上げます。
自動的に宣言されるargumentsは配列っぽい変数ですが、配列から継承して作られた存在ではなく、
リスト操作のメソッドを使おうとするとエラーが出ます。

参考サイト: [JavaScript] arguments をサクッと配列に変換する方法

JavaScript

1function calcSum() { 2 var args = Array.prototype.slice.call(arguments); 3 return args.reduce(function(a, b){ return a + b }, 0); 4} 5console.log(calcSum()); // 0 6console.log(calcSum(1)); // 1 7console.log(calcSum(1, 2)); // 3 8console.log(calcSum(1, 2, 3)); // 6 9console.log(calcSum(1, 2, 3, 4)); // 10

おまけのおまけ!: ES2015をフルに使った場合

maisumakun:
babelやNode前提の環境では、(同種の引数を任意個受ける、という状況なら)最後のようにspread引数として宣言しておくのがわかりやすい気もします。

JSも幾つかバージョンがあり、ES2015という新バージョンでは更に強化した記述が可能になりました。
アロー演算子、spread、reduceをフル活用すれば質問文の例題を1行で書けてしまいます。
残念ながらIE11では対応していませんが、他のモダンブラウザ全てとNode.jsでは扱えますので調べてみてください。

IE11に対応する場合、Babelという古いJSのバージョンに戻すソフトを使えば大体動作します。
自動化ツールを組んで、書いたコードをデプロイ前にBabelを通して反映するということが可能です。

JavaScript

1const calcSum = (...nums) => nums.reduce((a, b) => a + b, 0) 2console.log(calcSum()); // 0 3console.log(calcSum(1)); // 1 4console.log(calcSum(1, 2)); // 3 5console.log(calcSum(1, 2, 3)); // 6 6console.log(calcSum(1, 2, 3, 4)); // 10

投稿2017/11/18 09:04

編集2017/11/18 09:28
miyabi-sun

総合スコア21158

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

uer03108

2017/11/26 07:16

詳しいご解説有難うございました。 便利な演算子がありますね。 使いこなせればコードの可動性も上がりそうです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問