JavaScript関数のパラメータについて詳しく解説した記事
関数パラメーターは、関数の内部と関数の外部の間の橋渡しとなります。次の記事では、JavaScript 関数のパラメーターについて説明します。お役に立てば幸いです。
1. 関数パラメータと実際のパラメータ
関数のパラメータは、関数定義という 2 つの場所に表示されます。これら 2 つの場所のパラメータと関数呼び出し場所の違いです。
-
仮パラメータ (仮パラメータ)
関数定義に現れるパラメータは、データを持たないプレースホルダとみなすことができます。関数が呼び出されて渡されたデータを受け取るまで待つことしかできないため、これは仮パラメータ、または略して仮パラメータと呼ばれます。
-
実際のパラメータ (実際のパラメータ)
関数の呼び出し時に指定されるパラメータには実際のデータが含まれており、関数によって内部的に使用されます。コードを使用するため、実パラメータ、または略して実パラメータと呼ばれます。
仮パラメータと実際のパラメータの違いと関係
1) 仮パラメータ変数は、次の場合にのみ使用されます。関数が呼び出される メモリは呼び出し完了後にのみ割り当てられ、メモリはすぐに解放されるため、仮パラメータ変数は関数内でのみ有効であり、関数外では使用できません。
2) 実際のパラメータは、定数、変数、式、関数などです。実際のパラメータのデータの種類に関係なく、関数呼び出しを行うときは、特定の値が必要です。これらの値を仮パラメータに転送するには、事前に代入や入力などを使用して実パラメータの特定の値を取得する必要があります。
3) 実パラメータと仮パラメータは、数、型、順序が厳密に一致している必要があります。そうでないと、「型の不一致」エラーが発生します。もちろん、自動型変換が可能な場合や強制的に型変換を行った場合には、実パラメータの型が仮パラメータの型と異なる場合もあります。
4) 関数呼び出しで発生するデータ転送は一方向であり、仮パラメータに転送できるのは実パラメータの値のみですが、仮パラメータの値は転送できません。実パラメータ、つまりデータ転送が完了すると、実パラメータと仮パラメータは無関係になるため、関数呼び出し中にパラメータの値が変化します。仮パラメータは実際のパラメータには影響しません。
5) 仮パラメータと実パラメータは同じ名前を持つことができますが、実パラメータは関数の外部で有効であるため、それらは互いに独立しており、相互に影響しません。一方、仮パラメータは関数の内部にあり、効率的です。
仮パラメータと実パラメータの機能はデータを渡すことであり、関数呼び出しが発生すると、実パラメータの値が仮パラメータに渡されます。
2. パラメータの受け渡し
関数を使用するとデータを渡すことができ、渡されたデータは関数の実行結果に影響を与えるため、関数がより柔軟になり、再利用可能、より強力なセックス。
function foo(a, b) { console.log([a, b]); } foo(1, 2); // 输出 [1, 2]
この例では、a
と b
は関数内のローカル変数であり、関数内でのみアクセスできます。関数を呼び出すと、渡されたデータが位置に応じて照合され、それぞれ a
と b
に割り当てられます。
関数を作成するとき、関数関数名
の後の括弧内に設定されるパラメータは、仮パラメータと呼ばれます。関数を呼び出す場合、関数の後に括弧内に渡されるパラメータは、仮パラメータと呼ばれます。関数名 パラメータは 実際のパラメータ
と呼ばれます。上記の例では、a
と b
は仮パラメータであり、渡される 1
と
は実際のパラメータです。 仮パラメータは宣言された変数であるため、
let
および
を使用して繰り返し宣言することはできません。 function foo(a, b) {
let a = 1; // 报错,a 已声明
const b = 1; // 报错,b 已声明
}
function add(num) { return num + 1; } let count = 5; let result = add(count); // 此处参数传递的过程可以看作是 num = count console.log(count); // 5 console.log(result); // 6
function setName(obj) {
obj.name = "小明";
}
let person = {};
setName(person); // 此处参数传递的过程可以看作是 obj = person;
console.log(person); // {name: "小明"}
ログイン後にコピー
3. パラメータについて
JavaScript の関数は型を検出しませんのパラメータも検出されず、渡されたパラメータの数も検出されません。関数を定義するときに 2 つの仮パラメータを設定しても、呼び出し時に 2 つのパラメータを渡す必要があるという意味ではありません。実際に呼び出す場合、パラメータが 1 つであっても 3 つであっても、パラメータが渡されなかったとしてもエラーは報告されません。 function setName(obj) { obj.name = "小明"; } let person = {}; setName(person); // 此处参数传递的过程可以看作是 obj = person; console.log(person); // {name: "小明"}
すべての関数 (矢印以外) には、
arguments という名前の特別な 配列のようなオブジェクト (
Array のインスタンスではありません) があります。すべての実パラメータのコピーを保存します。これを使用して、配列のインデックス アクセス メソッドに従ってすべての実パラメータの値を取得したり、その
arguments.length
function foo(a, b) { console.log(arguments[0]); console.log(arguments[1]); console.log(arguments.length); } foo(10, 20); // 依次输出 10、20、2
function foo() { console.log(arguments[0]); console.log(arguments[1]); } foo(10, 20); // 依次输出 10、20
还有一个要注意的是,arguments
可以跟形参一起使用,并且 arguments
对象中的值会和对应的形参保持同步。例如:
function foo(a) { arguments[0] ++; console.log(a); } foo(10); // 输出 11 //------------------------------------ function foo2(a) { a++; console.log(arguments[0]); } foo2(10); // 输出 11
当修改 arguments[0] 或 a 的值时,另一个也被改变了。这并不意味着它们访问同一个内存地址,毕竟我们传入的是一个原始值。它们在内存中还是分开的,只是由于内部的机制使它们的值保持了同步。
另外,如果缺少传参,那这个形参的值就不会和 arguments
对象中的对应值进行同步。例如下面这个例子,只传了一个参数,那么arguments
中只有一个实参值,这时候在函数中把 arguments[1] 设置为某个值,这个值并不会同步给第二个形参,例如:
function foo(a,b) { arguments[1] = 2; console.log(b); } foo(1); // 输出 undefined
这个例子中,形参 b 没有传入实参,它的值会默认为 undefined
。但如果:
foo(1, undefined); // 输出 2
手动传入 undefined
时, arguments
数组中会出现一个值为 undefined
的元素,依然能和 b 的值进行同步。
严格模式下,arguments
对象中的值和形参不会再同步,当然,如果传入的是引用值,它们依然会互相影响,但这只是引用值的特性而已。因此,在开发中最好不要依赖这种同步机制,也就是说不要同时使用形参和它在arguments
对象中的对应值。
箭头函数中没有 arguments
如果函数是使用箭头语法定义的,那么函数中是没有 arguments 对象的,只能通过定义的形参来访问。
let foo = () => { console.log(arguments[0]); }foo(); // 报错,arguments 未定义
在某些情况可能会访问到 arguments
:
function fn1(){ let fn2 = () => { console.log(arguments[0]); } fn2(); }fn1(5);
但这个 arguments
,并不是箭头函数的,而是属于外部普通函数的,当箭头函数中访问 arguments
时,顺着作用域链找到了外部函数的arguments
。
四、将对象属性用作实参
当一个函数包含的形参有多个时,调用函数就成了一种麻烦,因为你总是要保证传入的参数放在正确的位置上,有没有办法解决传参顺序的限制呢?
由于对象属性是无序的,通过属性名来确定对应的值。因此可以通过传入对象的方式,以对象中的属性作为真正的实参,这样参数的顺序就无关紧要了。
function foo(obj) { console.log(obj.name, obj.sex, obj.age); } foo({ sex: '男', age: 18, name: '小明' }); // 小明 男 18
五、参数默认值
如果调用函数时缺少提供实参,那么形参默认值为 undefined
。
有时候我们想要设置特定的默认值,在 ES6 之前还不支持显式地设置默认值的时候,只能采用变通的方式:
function sayHi(name) { name = name || 'everyone'; console.log( 'Hello ' + name + '!'); } sayHi(); // 输出 'Hello everyone!'
通过检查参数值的方式判断有没有赋值,上面的做法虽然简便,但缺点在于如果传入的实参对应布尔值为 false
,实参就不起作用了。需要更精确的话可以用 if
语句或者三元表达式,判断参数是否等于 undefined
,如果是则说明这个参数缺失 :
// if 语句判断 function sayHi(name) { if (name === undefined) { name = 'everyone'; } console.log( 'Hello ' + name + '!'); } // 三元表达式判断 function sayHi(name) { name = (name !== undefined) ? name : 'everyone'; console.log( 'Hello ' + name + '!'); }
ES6 就方便了许多,因为它支持了显式的设置默认值的方式,就像这样:
function sayHi(name = 'everyone') { // 定义函数时,直接给形参赋值 console.log( 'Hello ' + name + '!'); } sayHi(); // 输出 'Hello everyone!' sayHi('Tony'); // 输出 'Hello Tony!' sayHi(undefined); // 输出 'Hello everyone!'
这些结果表明了,它也是通过参数是否等于 undefined
来判定参数是否缺失的。
默认值不但可以是一个值,它还可以是任意合法的表达式,甚至是函数调用:
function sayHi(name = 'every'+'one') { console.log( 'Hello ' + name + '!'); } sayHi(); // 输出 'Hello everyone!' //-------------------------------------- function foo() { console.log('调用foo'); return 'Tony'; } function sayHi(name = foo()) { console.log( 'Hello ' + name + '!'); } sayHi(); // 输出 '调用foo' // 输出 'Hello Tony!' sayHi(undefined); // 输出 '调用foo' // 输出 'Hello Tony!' sayHi('John'); // 输出 'Hello John!'
可以看到,函数参数的默认值只有在函数调用时,参数的值缺失或者是 undefined
才会求值,不会在函数定义时求值。
参数默认值的位置
通常我们给参数设置默认值,是为了调用函数时可以适当省略参数的传入,这里要注意的是,有多个参数时,设置了默认值的参数如果不是放在尾部,实际上它是无法省略的。
function fn(x = 1, y) { console.log([x, y]); } fn(); // 输出 [1, undefined] fn(2); // 输出 [2, undefined] fn(, 2); // 报错,语法错误(这里不支持像数组那样的空槽) fn(undefined, 2); // 输出 [1, 2] (那还不如传个 1 方便呢!)
上面例子中,给形参 x 设置的默认值就显得没有任何意义了。因此,设置默认值的参数放在尾部是最好的做法:
function fn(x, y = 2) { console.log([x, y]); } fn(); // 输出 [undefined, 2] fn(1); // 输出 [1, 2] fn(1, 1) // 输出 [1, 1]
参数的省略问题
在多个参数设置了默认值的情况下,那么问题又来了,你并不能省略比较靠前的参数,而只给最后的一个参数传入实参。
function fn(x, y = 2, z = 3) { console.log([x, y, z]); } fn(1, , 10) // 报错
前面我们知道,可以通过传入对象的这种方式去避免参数顺序的限制。那参数默认值如何实现呢?用 ||
、 if
语句或者三元表达式去判断也是解决办法,但这样就显得有些落后了。接下来要讨论的是另外两种 ES6 中的全新方式。
参数默认值和 Object.assign() 结合使用
function fn(obj = {}) { let defaultObj = { x: undefined, y: 2, z: 3 } let result = Object.assign(defaultObj, obj); console.log([result.x, result.y, result.z]); } fn(); // 输出 [undefined, 2, 3] fn({ x: 1, z: 10 }); // 输出 [1, 2, 10]
上面的例子中,在函数中定义了一个对象 defaultObj
,变通地利用其中的属性作为参数的默认值,然后利用 Object.assagin() 把传入的对象和默认对象进行合并,defaultObj 中的属性会被 obj 的相同属性覆盖,obj 中如果有其他属性会分配给 defaultObj 。这里用一个变量接收返回的合并对象。
同时形参 obj
也设置了默认值为一个空对象,防止函数调用时不传任何参数,因为这会导致 Object.assign() 接收的第二个参数是 undefined
,从而产生报错。
参数默认值和解构赋值结合使用
函数调用时,实参和形参的匹配实际上是一个隐式的赋值过程,所以,参数传递也可以进行解构赋值:
function fn({ x, y = 2, z = 3 }) { console.log([x, y, z]); } fn({}); // 输出 [undefined, 2, 3] fn({ x: 1, z: 10 }); // 输出 [1, 2, 10]
在这个例子中,使用的只是对象的解构赋值默认值,还没有使用函数参数的默认值。如果函数调用时不传任何参数,也会产生报错,因为这导致了参数初始化时解构赋值失败,相当于执行了 {x, y = 2, z = 3} = undefined
这样的代码。
同样的,你可以利用参数默认值的语法,给 {x, y = 2, z = 3}
设置一个默认的解构对象,使得不传参函数也能够顺利执行:
function fn({ x, y = 2, z = 3 } = {}) { console.log([x, y, z]); } fn(); // 输出 [undefined, 2, 3]
这里出现了双重的默认值,可能有些绕,那么用一段伪代码来解释以上的参数初始化过程就是:
if( 实参 === {...} ) { // 当 fn({...}); { x, y = 2, z = 3 } = {...}; } else if ( 实参 === undefined ){ // 当 fn(); { x, y = 2, z = 3 } = {}; }
双重默认值有一点细节需要特别注意,就是解构赋值默认值和函数参数默认值的差别,看下面例子:
function fn ({ x = 1 } = {}, { y } = { y: 2 }){ console.log(x, y); } fn(); // 输出 1 2 fn({ x: 10 }, { y: 20 }); // 输出 10 20 fn({},{}); // 1 undefined
这个函数中,有两组参数采用了解构赋值的方式,看似 x 和 y 都设置了默认值,虽然是不同的两种形式,但显然不是任何情况下结果都相同的。当传入的参数是{}
时,y 并没有获取到默认值 2 ,为什么会这样呢?结合前面的伪代码例子来看:
fn({ x: 10 }, { y: 20 }); // 初始化时: { x = 1 } = { x: 10 }, { y } = { y: 20 } fn({},{}); // 初始化时: { x = 1 } = {}, { y } = {}
当传入的参数是{}
时,函数参数没有缺失也不是 undefined
,所以函数参数默认值是不起作用的。同时 {}
里面也没有 x 和 y 的对应值,x 得到的 1 是解构赋值默认值,而 y 由于没有设置解构赋值默认值,所以它默认是 undefined
。
参数默认值的作用域与暂时性死区
还有一个小细节,一旦有参数设置了默认值,那么它们会形成自己的作用域(包裹在(...)
中),因此不能引用函数体中的变量:
function foo(a = b) { let b = 1; } foo(); // 报错,b 未定义
但这个作用域只是临时的,参数初始化完毕后,这个作用域就不存在了。
它也符合普通作用域的规则:
let b = 2; function foo(a = b) { let b = 1; return a; } foo(); // 2
上面例子中,存在一个全局变量 b,那么形参 a 会获取到全局变量 b 的值。
当然,如果形参作用域中存在一个形参 b 的话,它优先获取到的是当前作用域的:
let b = 2; function foo(b = 3 ,a = b) { return a; } foo(); // 3
给多个参数设置默认值,它们会按顺序初始化的,遵循“暂时性死区”的规则,即前面的参数不能引用后面的参数:
function foo(a = b, b = 2) { return a + b; } foo(); // 报错,b 在初始化之前不能访问
六、参数的收集与展开
剩余参数
ES6 提供了**剩余参数(rest)**的语法(...变量名
),它可以收集函数多余的实参(即没有对应形参的实参),这样就不再需要使用 arguments
对象来获取了。形参使用了 ...
操作符会变成一个数组,多余的实参都会被放进这个数组中。
剩余参数基本用法:
function sum(a, ...values) { for (let val of values) { a += val; } return a; } sum(0, 1, 2, 3); // 6
上面例子中,在参数初始化时,首先根据参数位置进行匹配,把 0 赋值给 a ,然后剩余的参数 1、2、3 都会被放进数组 values 中。
下面是分别用 arguments
对象和剩余参数来获取参数的对比例子:
// arguments 的写法 function sortNumbers() { return Array.prototype.slice.call(arguments).sort(); } // 剩余参数的写法 const sortNumbers = (...numbers) => { return numbers.sort(); }
可以看出剩余参数的写法更加简洁。尽管 arguments
是一个类数组,也是可迭代对象,但它终究不是数组。它不支持数组方法,当我们使用 arguments
时,如果想要调用数组方法,就必须使用Array.prototype.slice.call
先将其转为数组。
而剩余参数它不同于 arguments
对象,它是真正的 Array
实例,能够很方便地使用数组方法。并且箭头函数也支持剩余参数。
另外,使用剩余参数不会影响 arguments
对象的功能,它仍然能够反映调用函数时传入的参数。
剩余参数的位置
剩余参数必须是最后一个形参,否则会报错。
// 报错 function fn1(a, ...rest, b) { console.log([a, b, rest]); } // 正确写法 function fn2(a, b, ...rest) { console.log([a, b, rest]); } fn2(1, 2, 3, 4) // 输出 [1, 2, [3, 4]]
展开语法
前面我们知道了如何把多余的参数收集为一个数组,但有时候我们需要做一些相反的事,例如要把一个数组中的元素分别传入给某个函数,而不是传入一个数组,像这样:
function sum(...values) { let sum = 0; for (let val of values) { sum += val; } return sum; } let arr = [1, 2, 3, 4]; sum(arr); // "01,2,3,4"
上面例子的函数会把所有传进来的数值累加,如果直接传入一个数组,就得不到我们想要的结果。
例子中传入一个数组, values 的值会变成 [[1, 2, 3, 4]]
,导致数组 values 中只有一个元素,而这个元素的类型是数组。那么函数返回值就是数值 0
和数组 [1, 2, 3, 4]
相加的结果了,两者各自进行了类型的隐式转换变成字符串,然后再相加,是一个字符串拼接的效果。
要实现把数组拆解传入给函数,首先不可能一个个传入参数——sum(arr[0], arr[1], arr[2], arr[3]);
,因为不是任何时候都知道数组中有多少个元素的,而且数组中可能会非常多的元素,手动传是不明智的。
比较可行的是借助 apply() 方法:
sum.apply(null, arr); // 10
但这还不是最优解,那么重点来了!
ES6 新增的**展开语法(spread)**可以帮助我们面对这种情况。它也是使用 ...变量名
的语法,虽然跟剩余参数语法一样,但是用途完全相反,它能够把一个可迭代对象拆分成逗号分隔的参数序列。
在函数调用时,它的应用是这样子的:
sum(...arr); // 10 // 相当于 sum(1,2,3,4);
它甚至可以随意搭配常规值使用,没有前后位置限制,还可以同时传入多个可迭代对象:
sum(-1, ...arr); // 9 sum(...arr, 5); // 15 sum(-1, ...arr, 5); // 14 sum(-1, ...arr, ...[5, 6, 7]); // 27
展开操作符 ...
相当于替我们完成了手动分别传参的操作,函数只知道接收的实参是单独的一个个值,不会因为展开操作符的存在而产生其他影响。
上面的示例虽然都是针对于数组的,但展开语法能做的还不止这些,其他可迭代对象例如字符串、字面量对象都可以展开,深入了解请参见 → 展开语法
总结
形参是函数中已声明的局部变量,传递给函数的实参会被赋值给形参,函数参数传递实际上是一个隐式的赋值过程。
-
形参和实参的数量可以不相等:
● 缺失实参的形参会得到默认值
undefined
。● 额外的实参,可以通过
arguments
对象访问,箭头函数除外。 可以通过传入对象的方式让传参顺序不再重要,让对象中的属性作为真正的实参。
-
ES6 的参数默认值——函数调用时参数的值缺失或者是
undefined
,才会获取默认值。● 设置默认值的形参只有放在最后一位才可以省略传参。
● 形参设置默认值不能引用函数体中的变量,但可以引用前面的形参和外部变量。
● 通过 Object.assign() 或者解构赋值实现默认值,能让传参的方式更加灵活。
-
剩余参数和
arguments
的主要区别:● 剩余参数只包含那些没有对应形参的实参,而
arguments
对象包含了传给函数的所有实参。● 剩余参数是真正的
Array
实例,而arguments
只是类数组对象。 -
剩余参数和展开语法都采用
...
操作符,在函数的相关场景中:● 出现在函数形参列表的最后,它是剩余参数。
● 出现在函数调用时,它是展开语法。
【相关推荐:javascript学习教程】
以上がJavaScript関数のパラメータについて詳しく解説した記事の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック











関数パラメータの受け渡し方法とスレッド セーフ: 値の受け渡し: 元の値に影響を与えることなくパラメータのコピーを作成します。これは通常はスレッド セーフです。参照渡し: アドレスを渡し、元の値の変更を許可します。通常はスレッドセーフではありません。ポインターの受け渡し: アドレスへのポインターの受け渡しは参照による受け渡しに似ており、通常はスレッドセーフではありません。マルチスレッド プログラムでは、参照およびポインタの受け渡しは注意して使用する必要があり、データ競合を防ぐための措置を講じる必要があります。

C++ の不定パラメータの受け渡し: ... 演算子によって実装され、任意の数の追加パラメータを受け入れます。利点には、柔軟性、スケーラビリティ、コードの簡素化が含まれます。欠点には、パフォーマンスのオーバーヘッド、デバッグの困難、および型の安全性が含まれます。一般的な実践例には、va_list を使用して可変数のパラメーターを処理する printf() および std::cout が含まれます。

JavaScript チュートリアル: HTTP ステータス コードを取得する方法、特定のコード例が必要です 序文: Web 開発では、サーバーとのデータ対話が頻繁に発生します。サーバーと通信するとき、多くの場合、返された HTTP ステータス コードを取得して操作が成功したかどうかを判断し、さまざまなステータス コードに基づいて対応する処理を実行する必要があります。この記事では、JavaScript を使用して HTTP ステータス コードを取得する方法を説明し、いくつかの実用的なコード例を示します。 XMLHttpRequestの使用

JavaScript で HTTP ステータス コードを取得する方法の紹介: フロントエンド開発では、バックエンド インターフェイスとの対話を処理する必要があることが多く、HTTP ステータス コードはその非常に重要な部分です。 HTTP ステータス コードを理解して取得すると、インターフェイスから返されたデータをより適切に処理できるようになります。この記事では、JavaScript を使用して HTTP ステータス コードを取得する方法と、具体的なコード例を紹介します。 1. HTTP ステータス コードとは何ですか? HTTP ステータス コードとは、ブラウザがサーバーへのリクエストを開始したときに、サービスが

C++ で関数パラメータを渡すには、値による呼び出し (実際のパラメータに影響を与えない) と参照による呼び出し (実際のパラメータに影響を与える) の 2 つの方法があります。パラメータの受け渡しは参照またはポインタを渡すことによって実現され、関数はパラメータ参照またはポインタが指す変数を変更することによって呼び出し元に値を渡すことができます。使用時の注意点: 送信パラメータは明確に宣言する必要があり、実際のパラメータは 1 つだけ対応でき、関数内のローカル変数を指すことはできません。ポインタを渡して呼び出す場合は、ワイルド ポインタを避けるように注意してください。

PHP 関数のパラメーターの型には、スカラー型 (整数、浮動小数点数、文字列、ブール値、null 値)、複合型 (配列、オブジェクト)、特殊型 (コールバック関数、変数パラメーター) が含まれます。関数は、さまざまな型のパラメーターを自動的に変換できますが、偶発的な変換を防ぎ、パラメーターの正確性を確保するために、型宣言を通じて特定の型を強制することもできます。

はい、多くのプログラミング言語では、配列を関数のパラメーターとして使用でき、関数はそこに格納されているデータに対して操作を実行します。たとえば、C++ の printArray 関数は配列内の要素を出力できますが、Python の printArray 関数は配列を走査してその要素を出力できます。これらの関数によって配列に加えられた変更は、呼び出し関数の元の配列にも反映されます。

C++ で関数パラメーターの受け渡し方法を選択する場合、値による受け渡し、参照による受け渡し、ポインターによる受け渡し、const 参照による受け渡しの 4 つのオプションがあります。値渡しではパラメータ値のコピーが作成され、元のパラメータには影響しません。パラメータ値への参照を参照渡しすると、元のパラメータを変更できます。パラメータ値へのポインタをポインタで渡すと、元のパラメータを変更できます。ポインタを介して値を渡す; const 参照によってパラメータ値を渡す const 参照はパラメータ値にアクセスすることしかできず、パラメータ値を変更することはできません。
