JavaScript'teki bir sabitin değerini neden değiştirebilirim


103

ES6'nın henüz standartlaştırılmadığını biliyorum, ancak birçok tarayıcı şu anda const JS'de anahtar kelimeyi destekliyor .

Spesifikasyonda şöyle yazılır:

Bir sabitin değeri yeniden atama yoluyla değiştirilemez ve bir sabit yeniden beyan edilemez. Bu nedenle, bir sabiti ilklendirmeden ilan etmek mümkün olsa da, bunu yapmak faydasız olacaktır.

ve böyle bir şey yaptığımda:

const xxx = 6;
xxx = 999;
xxx++;
const yyy = [];
yyy = 'string';
yyy = [15, 'a'];

Her şeyin yolunda olduğunu görüyorum xxx, hala 6ve yyyöyle [].

Ama yaparsam yyy.push(6); yyy.push(1);sabit dizim değişti. Şu anda öyle [6, 1]ve bu arada hala değiştiremiyorum yyy = 1;.

Bu bir hata mı yoksa bir şey mi kaçırıyorum? En son chrome ve FF29'da denedim


1
Sadece bir sınıf oluşturabilir, değişkeni bildirebilir ve sınıfın içinde onun değerini atayabilir misiniz? Ardından, bu değişken için bir GETTER oluşturun; ve bir ayarlayıcı uygulamayın. Sabit bir ...
Andrew

8
@Andrew teşekkürler, ama bunu nasıl yapabilirim diye sormuyorum. Const anahtar kelimesinin neden bu şekilde davrandığını merak ediyorum.
Salvador Dali

Yanıtlar:


176

Belgeler şu şekildedir:

... sabit yeniden atama yoluyla değiştirilemez
... sabit yeniden bildirilemez

Sabiti yeniden atamadığınız veya yeniden bildirmediğiniz bir dizi veya nesneye ekleme yaparken, zaten bildirilmiş ve atanmış, sabitin işaret ettiği "listeye" eklemiş olursunuz.

Yani bu iyi çalışıyor:

const x = {};

x.foo = 'bar';

console.log(x); // {foo : 'bar'}

x.foo = 'bar2';

console.log(x); // {foo : 'bar2'}  

ve bu:

const y = [];

y.push('foo');

console.log(y); // ['foo']

y.unshift("foo2");

console.log(y); // ['foo2', 'foo']

y.pop();

console.log(y); // ['foo2']

ama bunların hiçbiri:

const x = {};
x = {foo: 'bar'}; // error - re-assigning

const y = ['foo'];
const y = ['bar']; // error - re-declaring

const foo = 'bar'; 
foo = 'bar2';       // error - can not re-assign
var foo = 'bar3';   // error - already declared
function foo() {};  // error - already declared

4
yani bunun bir hata olmadığını, ancak bu şekilde çalışması gerektiğini mi söylüyorsunuz? Çünkü sabit fikrinin değiştirilemeyeceğini düşündüm. Temel olarak bir programcı, ne olursa olsun sabitimin içindeki değeri hiçbir şeyin değiştiremeyeceğine güvenir.
Salvador Dali

2
Sanırım bu o kadar kolay değil, bu durumda sabitin değeri belirli öğelerden oluşan bir dizidir. Herhangi bir şeyi değiştirmek, değeri değiştirdiğiniz anlamına gelir .
veritas

6
Evet, bu şekilde çalışması gerekiyor, sabiti yeniden atamıyorsunuz, yine aynı referans, diziye sadece sabit referansları ekliyorsunuz ve diziler ve nesneler "listeler" gibidir, onları değiştirmek işe yarar referansı değiştirmeyin veya sabiti yeniden bildirmeyin.
adeneo

27
@SalvadorDali: Sabit ve salt okunur iki farklı şeydir. Değişkeniniz sabit , ancak işaret ettiği dizi salt okunur
Matt Burland

46

Bunun nedeni, sabitinizin aslında diziye bir başvuru depolamasıdır . Bir şeyi dizinize birleştirdiğinizde, sabit değerinizi değil, işaret ettiği diziyi değiştirmiş olursunuz. Bir sabite bir nesne atarsanız ve onun herhangi bir özelliğini değiştirmeye çalışırsanız aynı şey olur.

Bir diziyi veya nesneyi değiştirilemeyecek şekilde dondurmak istiyorsanız Object.freeze, zaten ECMAScript 5'in bir parçası olan yöntemi kullanabilirsiniz .

const x = Object.freeze(['a'])
x.push('b')
console.log(x) // ["a"]

1
Aynı mantıkla, five5'e ayarlanmış bir sabit aslında 5 değerine sahip değildir, bu sadece 5 sayısına bir referanstır. Yani eğer five++değiştirirsem sabiti değiştirmiyorum, sadece gösterdiği sayıyı.
Anthony

3
@Anthony, ilkel değerler için değil, yalnızca diziler ve nesneler için işe yarar
Guilherme Sehn

1
@Anthony Örneğinizde, değişkenin fiveişaret ettiği sayıyı değiştiriyorsunuz (değişken fiveeskiden 5 sayısı için bir etiketti, şimdi farklı bir sayıyı gösteriyor: 6). Sorudaki örnekte (ve bu cevap) xher zaman aynı listeye işaret eder; xconst ise , farklı bir listeye işaret edemezsiniz. Tek fark, aynı listenin büyüyüp küçülebilmesidir; bu, ilkeller için değil, yalnızca diziler ve nesneler için mümkün olan bir şeydir.
ShreevatsaR

9

Bu, aklıma gelen her programlama diliyle tutarlı bir davranış.

C - dizilerinin sadece yüceltilmiş işaretçiler olduğunu düşünün. Sabit bir dizi yalnızca göstericinin değerinin değişmeyeceği anlamına gelir - aslında bu adreste bulunan veriler serbesttir.

JavaScript'te, sabit nesnelerin yöntemlerini çağırmanıza izin verilir (tabii ki - aksi takdirde sabit nesneler pek bir amaca hizmet etmez!) Bu yöntemlerin nesneyi değiştirmenin yan etkisi olabilir. JavaScript'teki diziler nesne olduğundan, bu davranış onlar için de geçerlidir.

Emin olduğunuz tek şey, sabitin her zaman aynı nesneyi göstereceğidir. Nesnenin kendisinin özellikleri değiştirilebilir.


4

Const bildirimi, bir değere salt okunur bir başvuru oluşturur. Bu, tuttuğu değerin değişmez olduğu anlamına gelmez, sadece değişken tanımlayıcısının yeniden atanamayacağı anlamına gelir. Örneğin, içeriğin bir nesne olması durumunda, bu, nesnenin içeriğinin (örneğin, parametreleri) değiştirilebileceği anlamına gelir.

Ayrıca önemli bir not:

Global sabitler pencere nesnesinin özellikleri haline gelmez ...

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const


3

Bunun size konu hakkında daha fazla netlik sağlayacağını düşünüyorum: https://codeburst.io/explaining-value-vs-reference-in-javascript-647a975e12a0 .

Temel olarak const, bellekte her zaman aynı adresi göstermeye indirgenir . Bu adreste kayıtlı değeri değiştirebilir, ancak constişaret ettiği adresi de değiştiremezsiniz .

constBahsettiğiniz tanım, constilkel bir değeri olan bir adresi işaret ettiğinde doğru olacaktır . Bunun nedeni const, adresini değiştirmeden buna bir değer atayamamanızdır (çünkü ilkel değerler bu şekilde atanır ) ve a'nın adresini değiştirmeye constizin verilmez.

constİlkel olmayan bir değere işaret ediyormuş gibi , adresin değerini düzenlemek mümkündür.


2

Bir Nesneyi olarak tanımladıktan sonra bile neden güncelleyebildiğimi araştırırken bu makaleyi gözden geçirdim const. Yani buradaki nokta, doğrudan Nesne değil, içerdiği ve güncellenebilecek nitelikler olmasıdır.

Örneğin, Nesnem şöyle görünür:

const number = {
    id:5,
    name:'Bob'
};

Yukarıdaki cevaplar doğru bir şekilde nesnenin nesnenin özniteliği değil const olduğunu gösterdi. Dolayısıyla, şu işlemleri yaparak kimliği veya adı güncelleyebileceğim:

number.name = 'John';

Ancak, Nesnenin kendisini şu şekilde güncelleyemeyeceğim:

number = {
    id:5,
    name:'John'
  };

TypeError: Assignment to constant variable.


0

Const'ta bir nesnenin değerlerini değiştirebilirsiniz, böylece nesne aslında atama verilerini depolamaz, bunun yerine ona işaret eder. bu nedenle Javascript'teki ilkel öğeler ve nesneler arasında bir fark vardır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.