คำหลัก "const" ไม่ทำให้ค่าไม่เปลี่ยนรูป หมายความว่าอย่างไร?


85

มีคำจำกัดความของ constในการสำรวจ ES6โดย Dr. Axel Rauschmayer:

constทำงานเหมือนปล่อยให้ แต่ตัวแปรที่คุณประกาศจะต้องเริ่มต้นได้ทันทีที่มีค่าที่ไม่สามารถเปลี่ยนแปลงได้หลังจากนั้น […]

const bar = 123;
bar = 456;  // TypeError: `bar` is read-only

แล้วเขาก็เขียน

หลุมพราง: const ไม่ทำให้ค่าไม่เปลี่ยนรูป

const หมายความว่าตัวแปรจะมีค่าเท่ากันเสมอ แต่ไม่ได้หมายความว่าค่านั้นเป็นหรือไม่เปลี่ยนรูป

ฉันสับสนเล็กน้อยกับข้อผิดพลาดนี้ มีใครสามารถกำหนดข้อผิดพลาดconstนี้ให้ชัดเจนได้หรือไม่?


38
MDNคำอธิบายที่ชัดเจน: "ประกาศ const สร้างอ้างอิงอ่านอย่างเดียวให้เป็นค่าที่มันไม่ได้หมายความว่าค่ามันถือจะไม่เปลี่ยนรูปเพียงว่าตัวระบุตัวแปรไม่สามารถมีพระราชเสาวนีย์ยกตัวอย่างเช่นในกรณีที่เนื้อหาเป็น.. วัตถุซึ่งหมายความว่าวัตถุนั้นยังสามารถเปลี่ยนแปลงได้ " (เน้นของฉัน)
Gerardo Furtado

4
หมายความว่าถ้าค่าไม่แน่นอน (เช่นถ้าเป็นวัตถุ) คุณก็ยังสามารถกลายพันธุ์วัตถุนั้นได้ (เช่นอัพเดตเพิ่มลบคุณสมบัติ)
Felix Kling

2
const x = "immutable"ไม่เปลี่ยนรูปเพราะStringไม่เปลี่ยนรูป constห้ามเพียงการมอบหมายใหม่

3
@ibrahimmahrir: ผ่านอ้างอิง (สิ่งที่ไม่ JavaScript สำหรับวัตถุ) ไม่ได้เช่นเดียวกับการส่งผ่านโดยการอ้างอิง (ซึ่งอธิบายความสัมพันธ์ระหว่างการผูกค่าจะไม่เกี่ยวข้อง)
Felix Kling

2
@ibrahimmahrir: ใช่นั่นคือปัญหา คำที่ผ่านโดยการอ้างอิง มีความหมายที่เฉพาะเจาะจงมาก
Felix Kling

คำตอบ:


97

MDNสรุปได้อย่างสวยงาม:

การประกาศ const สร้างการอ้างอิงแบบอ่านอย่างเดียวสำหรับค่า ไม่ได้หมายความว่าค่าที่เก็บไว้จะไม่เปลี่ยนรูปเพียง แต่ไม่สามารถกำหนดตัวระบุตัวแปรใหม่ได้ ตัวอย่างเช่นในกรณีที่เนื้อหาเป็นวัตถุหมายความว่าวัตถุนั้นยังสามารถเปลี่ยนแปลงได้

รวบรัดมากขึ้น: const สร้างการเชื่อมโยงที่ไม่เปลี่ยนรูป

กล่าวอีกนัยหนึ่ง: const เช่น var ทำให้คุณมีหน่วยความจำที่ไม่แน่นอนซึ่งคุณจัดเก็บบางอย่าง อย่างไรก็ตาม const กำหนดว่าคุณต้องอ้างอิงไปยังหน่วยความจำเดียวกัน - คุณไม่สามารถกำหนดตัวแปรให้กับหน่วยความจำอื่นได้เนื่องจากการอ้างอิงตัวแปรเป็นค่าคงที่

Object.freeze()จริงๆทำอะไรบางอย่างที่ไม่มีการเปลี่ยนแปลงอย่างต่อเนื่องและหลังจากที่คุณได้ประกาศว่าคุณจะต้องใช้สิ่งที่ต้องการ อย่างไรก็ตามมันตื้นและใช้ได้กับคู่คีย์ / ค่าเท่านั้น การแช่แข็งทั้งวัตถุต้องใช้ความพยายามอีกเล็กน้อย การทำเช่นนั้นซ้ำ ๆ ในรูปแบบที่มีประสิทธิภาพนั้นท้าทายกว่า หากคุณต้องการสิ่งนั้นจริงๆขอแนะนำให้ตรวจสอบสิ่งต่างๆเช่นImmutable.js


20
ในเงื่อนไข C: ถ้าปกติvar xคือ a struct Object *x, a const xคือstruct Object *const x. ตัวชี้ไม่สามารถเปลี่ยนแปลงได้ สิ่งที่ชี้ไปที่ทำได้
คดีของ Fund Monica

151

เมื่อคุณสร้างบางสิ่งconstใน JavaScript คุณไม่สามารถกำหนดตัวแปรใหม่เพื่ออ้างอิงอย่างอื่นได้ อย่างไรก็ตามตัวแปรยังสามารถอ้างอิงวัตถุที่เปลี่ยนแปลงได้

const x = {a: 123};

// This is not allowed.  This would reassign `x` itself to refer to a
// different object.
x = {b: 456};

// This, however, is allowed.  This would mutate the object `x` refers to,
// but `x` itself hasn't been reassigned to refer to something else.
x.a = 456;

ในกรณีของสิ่งดั้งเดิมเช่นสตริงและตัวเลขconstนั้นง่ายกว่าที่จะเข้าใจเนื่องจากคุณไม่ได้เปลี่ยนค่า แต่จะกำหนดค่าใหม่ให้กับตัวแปรแทน


18
คำตอบนี้ดีกว่าคำตอบที่ยอมรับมาก รวบรัดมากขึ้นและมีโค้ดตัวอย่างจริง (กล่าวอีกนัยหนึ่งก็คือเข้าประเด็น ) +1
jpmc26

16

Rebinding

constและletการประกาศจะควบคุมว่าจะอนุญาตให้ทำการ rebindings (aka reassignments) ระหว่างตัวระบุและค่าหรือไม่

const x = "initial value";
let y = "initial value";

// rebinding/reassignment

try { x = "reassignment" } catch(e) { console.log(x) } // fails

y = "reassignment"; // succeeds
console.log(y);

ไม่เปลี่ยนรูป

ความไม่เปลี่ยนรูปถูกควบคุมที่ระดับประเภท Objectเป็นประเภทที่เปลี่ยนแปลงไม่ได้ในขณะStringที่ประเภทไม่เปลี่ยนรูป:

const o = {mutable: true};
const x = "immutable";

// mutations

o.foo = true; // succeeds
x[0] = "I"; // fails

console.log(o); // {mutable: true, foo: true}
console.log(x); // immutable


1

const หมายถึง: คุณไม่สามารถเปลี่ยนค่าที่กำหนดในตอนแรกได้

ขั้นแรกให้กำหนดค่าคืออะไรใน js คืออะไร ค่าอาจเป็น: บูลีนสตริงตัวเลขวัตถุฟังก์ชันและค่าที่ไม่ได้กำหนด

ชอบ: ผู้คนเรียกคุณด้วยชื่อของคุณมันไม่เปลี่ยนแปลง อย่างไรก็ตามคุณเปลี่ยนเสื้อผ้าของคุณ ความผูกพันระหว่างผู้คนและคุณคือชื่อของคุณ ส่วนที่เหลือสามารถเปลี่ยนแปลงได้ ขออภัยสำหรับตัวอย่างแปลก ๆ

ผมขอยกตัวอย่างบางส่วน:

// boolean
const isItOn = true;
isItOn = false;           // error

// number
const counter = 0;
counter++;                // error

// string
const name = 'edison';
name = 'tesla';           // error

// objects
const fullname = {
  name: 'albert',
  lastname: 'einstein'
};

fullname = {              // error
  name: 'werner',
  lastname: 'heisenberg'
};
// NOW LOOK AT THIS:
//
// works because, you didn't change the "value" of fullname
// you changed the value inside of it!
fullname.name = 'hermann';

const increase = aNumber => ++aNumber;
increase = aNumber => aNumber + 1;      // error

// NOW LOOK AT THIS:
//
// no error because now you're not changing the value
// which is the decrease function itself. function is a
// value too.
let anotherNumber = 3;
const decrease = () => --anotherNumber;

anotherNumber = 10;             // no error
decrease();                     // outputs 9

const chaos = undefined;
chaos = 'let there be light'    // error

const weird = NaN;
weird = 0                       // error

อย่างที่คุณเห็นเว้นแต่คุณจะไม่เปลี่ยนค่าที่กำหนด"แรก" เป็นค่า const ไม่มีข้อผิดพลาด เมื่อใดก็ตามที่คุณพยายามเปลี่ยนค่าที่กำหนดครั้งแรกไปเป็นอย่างอื่นมันจะโกรธและทำให้เกิดข้อผิดพลาด

constดังนั้นนี้เป็นสิ่งที่สองที่คุณอาจจะรู้ว่าเมื่อมีการใช้ ซึ่งก็คือควรเริ่มต้นให้เป็นค่าที่ประกาศไม่เช่นนั้นจะโกรธ

const orphan;                    // error
const rich = 0;                  // no error

0

ES6/ES2015 constคำหลัก:

constคำหลักที่จะใช้ในการประกาศตัวแปรบล็อกขอบเขต (เช่นประกาศด้วยlet) ความแตกต่างระหว่างการประกาศตัวแปรด้วยconstและletมีดังต่อไปนี้:

  1. constไม่สามารถกำหนดตัวแปรที่ประกาศ ใหม่ได้ได้
  2. ตัวแปรประกาศด้วยconstจะต้องมีการมอบหมายเมื่อประกาศ นี่คือเหตุผลสำคัญของจุดก่อนหน้านี้เพราะตัวแปรประกาศด้วยconstไม่สามารถมีพระราชเสาวนีย์ว่าทำไมเราจะต้องกำหนดว่าครั้งเดียวเมื่อเราประกาศตัวแปร

ตัวอย่าง:

// we declare variable myVariable
let myVariable;

// first assignment
myVariable = 'First assingment';
// additional assignment
myVariable = 'Second assignment';

// we have to declare AND initialize the variable at the same time
const myConstant = 3.14;

// This will throw an error
myConstant = 12;

ในตัวอย่างข้างต้นเราสามารถสังเกตสิ่งต่อไปนี้:

  1. ตัวแปรที่myVariableประกาศด้วยletสามารถประกาศก่อนแล้วจึงกำหนด
  2. ตัวแปรที่myConstantประกาศด้วยconstจะต้องได้รับการประกาศและกำหนดพร้อมกัน
  3. เมื่อเราพยายามกำหนดตัวแปรใหม่myConstantเราได้รับข้อผิดพลาดต่อไปนี้:

Uncaught TypeError: การกำหนดให้ตัวแปรคงที่

ข้อแม้: ตัวแปรที่กำหนดconstยังคงไม่แน่นอน:

ตัวแปรที่ประกาศโดยconstไม่สามารถกำหนดใหม่ได้ แต่ยังคงเปลี่ยนแปลงได้ การไม่เปลี่ยนแปลงหมายความว่าโครงสร้างข้อมูล (ออบเจ็กต์อาร์เรย์แผนที่ ฯลฯ ) ที่กำหนดให้กับconstตัวแปรยังคงสามารถเปลี่ยนแปลงได้ (เช่นกลายพันธุ์) ตัวอย่างของการกลายพันธุ์ ได้แก่ :

  1. การเพิ่ม / ลบ / แก้ไขคุณสมบัติของวัตถุ
  2. การเปลี่ยนค่าของอาร์เรย์ที่ดัชนีอาร์เรย์เฉพาะ

หากต้องการให้วัตถุไม่เปลี่ยนแปลงคุณจะต้องใช้สิ่งที่ต้องการ Object.freeze()ถ้าอยากวัตถุที่จะไม่แน่นอนคุณจะต้องใช้สิ่งที่ต้องการนี่คือวิธีการหยุดวัตถุ ไม่สามารถเปลี่ยนแปลงวัตถุแช่แข็งได้อีกต่อไปและไม่สามารถเพิ่มคุณสมบัติใหม่ได้

ตัวอย่าง:

const obj = {prop1: 1};

obj.prop1 = 2;
obj.prop2 = 2;

console.log(obj);

// We freeze the object here
Object.freeze(obj);

obj.prop1 = 5;
delete obj.prop2;

// The object was frozen and thus not mutated
console.log(obj);

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.