สองเซ็นต์ของฉัน ... นี่คือวิธีที่ฉันเข้าใจ (อย่าลังเลที่จะแก้ไขฉันถ้าฉันผิด)
ได้เวลาโยนทุกสิ่งที่คุณรู้เกี่ยวกับการส่งผ่านตามค่า / การอ้างอิง
เพราะในจาวาสคริปต์มันไม่สำคัญว่าจะถูกส่งผ่านตามค่าหรืออ้างอิงหรืออะไรก็ตาม สิ่งที่สำคัญคือการกลายพันธุ์และการกำหนดพารามิเตอร์ที่ส่งผ่านไปยังฟังก์ชัน
ตกลงให้ฉันทำอย่างดีที่สุดเพื่ออธิบายสิ่งที่ฉันหมายถึง สมมติว่าคุณมีวัตถุบางอย่าง
var object1 = {};
var object2 = {};
สิ่งที่เราทำคือ "การมอบหมาย" ... เราได้กำหนดวัตถุว่างเปล่า 2 อันแยกกันให้กับตัวแปร "object1" และ "object2"
ทีนี้สมมติว่าเราชอบ object1 ดีกว่า ... ดังนั้นเรา "กำหนด" ตัวแปรใหม่
var favoriteObject = object1;
ต่อไปไม่ว่าด้วยเหตุผลใดเราตัดสินใจว่าเราชอบวัตถุ 2 ดีกว่า ดังนั้นเราเพียงแค่ทำการมอบหมายใหม่เล็กน้อย
favoriteObject = object2;
ไม่มีอะไรเกิดขึ้นกับ object1 หรือ object2 เราไม่ได้เปลี่ยนแปลงข้อมูลใด ๆ เลย สิ่งที่เราทำก็คือกำหนดสิ่งที่วัตถุที่เราโปรดปรานอีกครั้ง สิ่งสำคัญคือต้องรู้ว่า object2 และ FavoriteObject ได้รับการกำหนดให้กับวัตถุเดียวกัน เราสามารถเปลี่ยนวัตถุนั้นผ่านตัวแปรเหล่านั้น
object2.name = 'Fred';
console.log(favoriteObject.name) // Logs Fred
favoriteObject.name = 'Joe';
console.log(object2.name); // Logs Joe
ตกลงตอนนี้เรามาดูตัวอย่างพื้นฐานเช่นสตริง
var string1 = 'Hello world';
var string2 = 'Goodbye world';
อีกครั้งเราเลือกรายการโปรด
var favoriteString = string1;
ทั้งตัวแปร FavoriteString และ string1 ของเราถูกกำหนดให้กับ 'Hello world' ทีนี้ถ้าหากเราต้องการเปลี่ยนแถบรายการโปรดของเรา ??? อะไรจะเกิดขึ้น???
favoriteString = 'Hello everyone';
console.log(favoriteString); // Logs 'Hello everyone'
console.log(string1); // Logs 'Hello world'
อ๊ะ .... เกิดอะไรขึ้น เราไม่สามารถเปลี่ยน string1 ได้โดยเปลี่ยนสายรายการโปรด ... ทำไม ?? เพราะเราไม่ได้เปลี่ยนสตริงของเราวัตถุ สิ่งที่เราทำคือ "RE ASSIGN" ตัวแปร FavoriteString เป็นสตริงใหม่ สิ่งนี้ตัดการเชื่อมต่อจาก string1 เป็นหลัก ในตัวอย่างก่อนหน้านี้เมื่อเราเปลี่ยนชื่อวัตถุเราไม่ได้มอบหมายอะไรเลย (ไม่ใช่สำหรับตัวแปรเอง ... เราทำ แต่กำหนดคุณสมบัติชื่อให้กับสตริงใหม่) แต่เราเพียงแค่กลายพันธุ์วัตถุซึ่งทำให้การเชื่อมต่อระหว่างตัวแปร 2 กับวัตถุต้นแบบ (แม้ว่าเราต้องการแก้ไขหรือกลายพันธุ์วัตถุสตริงเองเราไม่สามารถทำได้เพราะสตริงนั้นไม่เปลี่ยนรูปได้จริงใน JavaScript)
ทีนี้ไปที่ฟังก์ชั่นและพารามิเตอร์ที่ส่งผ่าน .... เมื่อคุณเรียกใช้ฟังก์ชั่นและส่งผ่านพารามิเตอร์สิ่งที่คุณกำลังทำอยู่ก็คือ "การมอบหมาย" ให้กับตัวแปรใหม่และมันทำงานเหมือนกับที่คุณได้รับมอบหมาย เครื่องหมายเท่ากับ (=)
นำตัวอย่างเหล่านี้
var myString = 'hello';
// Assign to a new variable (just like when you pass to a function)
var param1 = myString;
param1 = 'world'; // Re assignment
console.log(myString); // Logs 'hello'
console.log(param1); // Logs 'world'
ตอนนี้สิ่งเดียวกัน แต่มีฟังก์ชั่น
function myFunc(param1) {
param1 = 'world';
console.log(param1); // Logs 'world'
}
var myString = 'hello';
// Calls myFunc and assigns param1 to myString just like param1 = myString
myFunc(myString);
console.log(myString); // logs 'hello'
ตกลงตอนนี้เราจะยกตัวอย่างการใช้วัตถุแทน ... ก่อนโดยไม่มีฟังก์ชั่น
var myObject = {
firstName: 'Joe',
lastName: 'Smith'
};
// Assign to a new variable (just like when you pass to a function)
var otherObj = myObject;
// Let's mutate our object
otherObj.firstName = 'Sue'; // I guess Joe decided to be a girl
console.log(myObject.firstName); // Logs 'Sue'
console.log(otherObj.firstName); // Logs 'Sue'
// Now, let's reassign the variable
otherObj = {
firstName: 'Jack',
lastName: 'Frost'
};
// Now, otherObj and myObject are assigned to 2 very different objects
// And mutating one object has no influence on the other
console.log(myObject.firstName); // Logs 'Sue'
console.log(otherObj.firstName); // Logs 'Jack';
ตอนนี้สิ่งเดียวกัน แต่มีฟังก์ชั่นการโทร
function myFunc(otherObj) {
// Let's mutate our object
otherObj.firstName = 'Sue';
console.log(otherObj.firstName); // Logs 'Sue'
// Now let's re-assign
otherObj = {
firstName: 'Jack',
lastName: 'Frost'
};
console.log(otherObj.firstName); // Logs 'Jack'
// Again, otherObj and myObject are assigned to 2 very different objects
// And mutating one object doesn't magically mutate the other
}
var myObject = {
firstName: 'Joe',
lastName: 'Smith'
};
// Calls myFunc and assigns otherObj to myObject just like otherObj = myObject
myFunc(myObject);
console.log(myObject.firstName); // Logs 'Sue', just like before
ตกลงถ้าคุณอ่านโพสต์ทั้งหมดนี้บางทีตอนนี้คุณมีความเข้าใจที่ดีขึ้นเกี่ยวกับการทำงานของการโทรใน JavaScript มันไม่สำคัญว่าจะมีบางสิ่งบางอย่างถูกส่งผ่านโดยการอ้างอิงหรือตามค่า ... สิ่งสำคัญคือการมอบหมายกับการกลายพันธุ์
ทุกครั้งที่คุณส่งตัวแปรไปยังฟังก์ชั่นคุณจะ "กำหนด" ให้กับชื่อของตัวแปรพารามิเตอร์ใด ๆ เช่นถ้าคุณใช้เครื่องหมายเท่ากับ (=)
โปรดจำไว้เสมอว่าเครื่องหมายเท่ากับ (=) หมายถึงการมอบหมาย โปรดจำไว้เสมอว่าการส่งพารามิเตอร์ไปยังฟังก์ชันใน JavaScriptก็หมายถึงการกำหนดเช่นกัน พวกเขาเหมือนกันและตัวแปร 2 ตัวเชื่อมต่อกันด้วยวิธีเดียวกัน (ซึ่งก็คือพวกเขาไม่ได้เว้นแต่ว่าคุณจะได้รับมอบหมายให้เป็นวัตถุเดียวกัน)
ครั้งเดียวที่ "การแก้ไขตัวแปร" มีผลต่อตัวแปรที่แตกต่างกันคือเมื่อวัตถุต้นแบบถูกทำให้กลายพันธุ์ (ซึ่งในกรณีนี้คุณยังไม่ได้แก้ไขตัวแปร แต่เป็นวัตถุเอง
ไม่มีจุดใดที่ทำให้ความแตกต่างระหว่างวัตถุกับวัตถุพื้นฐานเพราะมันทำงานในลักษณะเดียวกันกับที่คุณไม่มีฟังก์ชั่นและใช้เครื่องหมายเท่ากับเพื่อกำหนดให้กับตัวแปรใหม่
gotcha เพียงอย่างเดียวคือเมื่อชื่อของตัวแปรที่คุณส่งเข้าไปในฟังก์ชันนั้นเหมือนกับชื่อของพารามิเตอร์ฟังก์ชัน เมื่อสิ่งนี้เกิดขึ้นคุณจะต้องปฏิบัติต่อพารามิเตอร์ภายในฟังก์ชั่นราวกับว่ามันเป็นตัวแปรใหม่ทั้งหมดของฟังก์ชั่นส่วนตัว (เพราะมันเป็น)
function myFunc(myString) {
// myString is private and does not affect the outer variable
myString = 'hello';
}
var myString = 'test';
myString = myString; // Does nothing, myString is still 'test';
myFunc(myString);
console.log(myString); // Logs 'test'