Javascript'te Type Coercion tam olarak nedir?


122

Javascript'te tür zorlaması tam olarak nedir?

Örneğin, ==yerine ===?


21
(true == 1) => true/ (true === 1) => false.
VisioN

5
@VisioN yorumunuz hiç yardımcı olmuyor, soruyorum: "neden" bu oluyor?
gespinha

3
Böyle olur çünkü JavaScript bu şekilde geliştirildi. Yorumum ana sorunuza cevap vermeli: Javascript'te Type Coercion tam olarak nedir?
VisioN

6
YDJS ile: "Bir değerin bir türden diğerine dönüştürülmesi, genellikle açık bir şekilde yapıldığında" tür atama "ve örtük olarak yapıldığında" zorlama "olarak adlandırılır (bir değerin nasıl kullanıldığına ilişkin kurallar tarafından zorlanır)." - github.com/getify/You-Dont-Know-JS/blob/master/…
mattLummus

Yanıtlar:


177

Tür zorlaması, bir işlecin işlenenleri farklı türler olduğunda, bunlardan birinin diğer işlenenin türünün "eşdeğer" değerine dönüştürüleceği anlamına gelir. Örneğin, yaparsanız:

boolean == integer

boole işleneni bir tam sayıya dönüştürülür: falseolur 0, 1 trueolur. Ardından iki değer karşılaştırılır.

Ancak, dönüştürmeyen karşılaştırma işlecini kullanırsanız ===, böyle bir dönüştürme gerçekleşmez. İşlenenler farklı türdeyse, bu operatör döndürür falseve değerleri yalnızca aynı türden olduklarında karşılaştırır.


1
Bunu pratik bir duruma nasıl koyabilirim? ===Bir değerin diğerine eşit olup olmadığını karşılaştırmak istediğimde her zaman kullanmam gerekmez mi?
gespinha

1
Ne yaptığına bağlı. Bağlantılı soruya bakın.
Barmar

8
@GEspinha iyi yazılmış bir dil kullanma "sanatı". Bazı insanlar böyle düşünüyor ve genel olarak gevşek yazılmış dillerin programlama dünyasının belası olduğunu düşünüyor. Bununla birlikte, ne yaptığınızı biliyorsanız, daha kısa, daha esnek kodlar oluşturabilir.
Crayon Violent

2
@Barmar da geçerli > , <mi?
Royi Namir

2
Zorlama üzerine mükemmel bir referans ve açıklama: github.com/getify/You-Dont-Know-JS/blob/master/…
Greg Bell

57

Tip zorlaması genel fikrini anlamanıza yardımcı olacağını düşündüğüm tip sistemlerine kısa bir giriş ile başlayalım.

Bir dilin tür sistemi, bize o dilde ne tür verilerin bulunduğunu ve farklı operatörler kullanılarak nasıl birleştirilebileceklerini söyleyen kuralları tanımlar. Örneğin, böyle bir kural, artı (+) operatörünün yalnızca sayılar üzerinde işlem yapacağını belirtebilir. Bu kurallar öncelikle kendinizi ayağınıza vurmanızı önlemek için var. Peki programcı programda bu kuralı ihlal ederse ne olur? Dil, bu ifadelerin herhangi bir anlam ifade etmediğini düşünse bile , programcının bir program yazmasını {} + {}veya “hello” + 5bir programın içine girmesini engelleyen hiçbir şey yoktur .

Bu durumlarda nihayetinde ne olacağı, dilin tür kuralları konusunda ne kadar katı olduğuna bağlıdır.

Bir dil türü sistemi, kurallarını ihlal ettiğinizle ilgili genellikle iki konumdan birini barındırır:

  1. "Hey, bu hiç hoş değil!" Deyin ve hemen programınızı kilitleyin.
  2. "{} İle hiçbir şey yapamam… ama sayılarla bir şeyler yapabilirim" deyin ve {} 'i bir sayıya dönüştürmeyi deneyin.

Kurallarıyla ilgili ilk sırayı alan yazı sistemlerine sahip diller, halk dilinde “güçlü yazılmış” diller olarak anılır. Kurallarını çiğnemenize izin vermemek konusunda katıdırlar. İkinci yaklaşımı benimseyenler (JavaScript gibi), "zayıf yazılmış" veya "gevşek yazılmış" diller olarak adlandırılır. Elbette, kuralları çiğneyebilirsiniz, ancak programınızda tanımladığınız veri türünü, kurallarına uymak için zorla dönüştürdüğünde şaşırmayın. Bu davranış… (davul sesi) ... tipi zorlama olarak bilinir .

Şimdi JavaScript'teki bazı örneklere bakalım. İlk olarak, tür zorlamasına yol açmayan bir ifadeyle başlayalım.

5 + 5

+ İşlecini iki sayı ile kullanmak tamamen geçerli. Program, + ile "ekle" anlamına gelir ve mutlu bir şekilde iki sayıyı ekler. Dönüştürmeye gerek yok.

Ama ne hakkında …

[] + 5

Maalesef JavaScript'te, +iki sayı eklemek veya iki dizeyi birleştirmek anlamına gelebilir. Bu durumda, ne iki sayımız ne de iki dizimiz var. Sadece bir numaramız ve bir nesnemiz var. JavaScript'in tür kurallarına göre, bu mantıklı değil. Kurallarını çiğnemeni bağışladığı için, çökmek yerine yine de anlamaya çalışıyor. Peki JavaScript ne yapar? Peki, dizeleri nasıl birleştireceğini biliyor, bu nedenle hem [] hem de 5'i dizelere dönüştürüyor ve sonuç "5" dize değeridir.

Karşılaştırma operatörleri ile anlaşma nedir ==ve ===? Neden iki karşılaştırma operatörü var?

==JavaScript'in tür dönüştürme davranışından etkilenmez. 5 == “5”JavaScript, bunlardan birini aynı tür verileri karşılaştırmak için dönüştürmeye çalışacağından gibi ifadeler doğru olarak değerlendirilir.

Çoğu durumda, bu arzu edilmez çünkü muhtemelen karşılaştırdığınız bazı verilerin farklı türde olup olmadığını bilmek istersiniz, böylece bu konuda ne yapacağınıza karar verebilirsiniz. ===Operatörün devreye girdiği yer burasıdır . Kullandığınızda ===, tip dönüşümü gerçekleşmez. Bu nedenle, ifade 5 === “5”yanlış olarak değerlendirilecektir.


4
Güzel açıklama için teşekkürler, özellikle "Bir dil türü sistemi genellikle iki konumdan birini tutar" için
Humoyun Ahmad

1
Otomatik tür zorlamasını yalnızca == karşılaştırma örneğini değil, birden çok yönden de gösterdiğinden, bu kabul edilen yanıt olmalıdır. Bu yanıt, soruyu yanıtlama ve tüm belirsizliği ortadan kaldırma konusunda çok daha iyi bir genel iş çıkarır. Yazmak için zaman ayırdığınız için teşekkür ederiz.
the chad

6

Python'da, dizeler ve tam sayılar eklemeye çalışırsanız, bir hata alırsınız:

>>> "hi" + 10
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: cannot concatenate 'str' and 'int' objects

Yine de JavaScript'te yapmazsınız. 10Bir dizeye dönüştürülür alır:

> "hi" + 10
"hi10"

"Tip zorlaması" yukarıdakiler için sadece süslü bir yanlış isimdir. Gerçekte, hiçbir dilin Java veya C anlamında "türleri" veya statik tip sistemli diğer dilleri yoktur. Dillerin, statik olmayan tipte çeşitli değerler arasındaki etkileşimleri nasıl ele aldığı bir seçim ve konvansiyon meselesidir.


1
Sanırım aldığınız örnekle ilgili bir miktar sorun var. JS'ye örnek olarak önerdiğiniz şey, Java ve C # ile kusursuz çalışıyor. Öyleyse, bu cevaba göre, Java ve C #' nin tamamen doğru olmayacak tür zorlamayı desteklediği sonucuna varılırsa ...
Romeo Sierra

3

tür zorlamasını aşağıdaki örnekle açıklamama izin verin

Tür Zorlama, Javascript'in bir değişkeni bir veri türünden diğerine otomatik olarak (anında) dönüştürdüğü anlamına gelir

Ör: 123 + "4"genellikle bir hata ortaya çıkarır, ancak tür zorlaması nedeniyle Javascript'te 1234bir dizeyle sonuçlanır

if(23 == "23"){
    console.log(" this line is inside the loop and is executed ");
}

Yukarıdaki kodda, tür zorlaması nedeniyle - JavaScript, 23(sayı) ve "23"(dizenin) aynı şey olduğunu düşünüyor . bu, koşulu doğru yapar ve console.log'u yazdırır.

Diğer durumda

if(23 === "23"){
   console.log(" this line is inside the loop and is NOT executed");
}

Gelen ===durumunda JavaScript Tipi Zorlama yapmaz, ve o zamandan beri 23bir sayıdır ve "23"dize olup nedeniyle ===bu iki veri türleri farklıdır ve koşul false olarak bu yol açar. Console.log dosyasını yazdırmaz

Basit bir deyişle

Bu durumda, =bu bir atama operatörüdür - var a = 3;vb. Gibi değerler atar.

(aşağıdaki operatörler karşılaştırma içindir)

Bu durumda ==Javascript, veri tipini diğerine dönüştürür / zorlar ve ardından onu karşılaştırır.

Bu durumda, === Javascript veri türünü dönüştürmez / zorlar

Hatalardan kaçınmak ve hata ayıklama amacıyla ===çoğunlukla kullanılır

Lütfen yukarıdaki bilgilerin doğruluğunu bana bildirin.


2

Zorlama nedir:

Javascript'te tür zorlaması, Javascript motorunun verinin belirli bir türde olması gereken belirli bir işlemi gerçekleştirmesi gerektiğinde oluşur. Motor, işlem için geçerli olmayan belirli bir türdeki verilerle karşılaştığında, verileri belirli bir türe zorlar. Bu gereklidir, çünkü javascript'teki değişkenler dinamik olarak türlenmiştir, bu, belirli bir değişkene herhangi bir türden bir değer atanabileceği anlamına gelir.

Misal:


if(1){
  // 1 gets coerced to true
}


if(4 > '3') {
  // 3 gets coerced into a number
}


44 == "44"  // true, the string 44 gets converted to a nr

Boole zorlaması:

Javascript zorlamasında, truezorlanan aşağıdaki değerler dışında tüm değerler dönüştürülür false:

console.log(!!"");         // false
console.log(!!0);          // false
console.log(!!null);       // false
console.log(!!undefined);  // false
console.log(!!NaN);        // false
console.log(!!false);      // false

Ayrıca yukarıdaki örnekte double! operatör kullanılır. ! mark operatörü, bir değeri zıt değere sahip bir mantıksal değere zorlar. Herhangi bir değeri boolean'a dönüştürmek için bu operatörü iki kez kullanabiliriz.


1

a == bdeğerlendirecek JavaScript aracı akarşı bdeğerleri aynı değerlendirilebilir eğer göre. Örneğin, false == 00 aynı zamanda Boolean false değerinin de olması nedeniyle true olarak değerlendirilir. Bununla birlikte, false === 0yanlış olarak değerlendirilecektir çünkü kesinlikle karşılaştırılırsa, 0, yanlış ile aynı fiziksel değer değildir. Başka bir örnek, false == ''temelde gevşek karşılaştırma ile katı karşılaştırmadır, çünkü javascript gevşek yazılmış bir dildir. Diğer bir deyişle, javascript değişkeni kodun bağlamına göre dönüştürmeye çalışacaktır ve bu, kesinlikle karşılaştırılmadıkları takdirde her şeyi eşit yapma etkisine sahiptir. php de bu davranışa sahiptir.


0 is not the same physical value as false. IMO fiziksel falseolarak tam 0olarak hafızadadır. Türe göre farklı olduklarını söylemeyi tercih ederim, çünkü falsemantıksaldır, oysa 0tamsayıdır.
VisioN

1

Tür zorlaması , değeri bir türden diğerine dönüştürme işlemidir (dizeden sayıya, nesneden mantıksal değere vb.). İster ilkel ister nesne olsun herhangi bir tür, tür zorlaması için geçerli bir konudur. Hatırlamak gerekirse, ilkeller şunlardır: sayı, dize, boole, null, tanımsız + Sembol (ES6'da eklenmiştir).

Örtük ve açık zorlama Tür zorlama açık ve örtük olabilir.

Bir geliştirici, uygun kodu yazarak türler arasında dönüştürme yapma niyetini ifade ettiğinde Number(value), buna açık tür zorlama (veya tür dönüştürme) denir.

JavaScript zayıf yazılmış bir dil olduğundan, değerler farklı türler arasında otomatik olarak dönüştürülebilir ve buna örtük tür zorlaması denir. Eğer farklı tipte gibi değerlerine operatörleri uyguladığınızda Genellikle olur 1 == null, 2/’5', null + new Date(), ya da olduğu gibi, çevredeki bağlamda tarafından tetiklenebilir if (value) {…}değeri boolean zorla nerede.

Örtük tür zorlamasını tetiklemeyen bir ===operatör, katı eşitlik operatörü olarak adlandırılan operatördür. ==Öte yandan gevşek eşitlik operatörü , gerekirse hem karşılaştırma hem de tür zorlaması yapar.

Örtülü tip zorlama çift kenarlı bir kılıçtır: büyük bir hayal kırıklığı ve kusur kaynağıdır, ancak aynı zamanda okunabilirliği kaybetmeden daha az kod yazmamızı sağlayan kullanışlı bir mekanizmadır.

Üç tür dönüşüm Bilinmesi gereken ilk kural, JavaScript'te yalnızca üç tür dönüşüm olduğudur:

  • dizeye
  • Boolean'a
  • numaraya

İkinci olarak, ilkeller ve nesneler için dönüştürme mantığı farklı çalışır, ancak hem ilkel öğeler hem de nesneler yalnızca bu üç şekilde dönüştürülebilir.

Önce ilkellerle başlayalım.

Dize dönüşümü

Değerleri açıkça bir dizeye dönüştürmek için String () işlevini uygulayın. Herhangi bir işlenen bir dizge olduğunda, örtülü zorlama ikili + operatörü tarafından tetiklenir:

String(123) // explicit
123 + ''    // implicit

Tüm ilkel değerler, beklediğiniz gibi doğal olarak dizelere dönüştürülür:

String(123)                   // '123'
String(-12.3)                 // '-12.3'
String(null)                  // 'null'
String(undefined)             // 'undefined'
String(true)                  // 'true'
String(false)                 // 'false'

Sembol dönüşümü biraz zordur çünkü yalnızca açıkça dönüştürülebilir, ancak dolaylı olarak dönüştürülemez.

String(Symbol('my symbol'))   // 'Symbol(my symbol)'
'' + Symbol('my symbol')      // TypeError is thrown

Boole dönüşümü

Bir değeri açıkça boolean'a dönüştürmek için Boolean()işlevi uygulayın . Örtük dönüştürme mantıksal bağlamda gerçekleşir veya mantıksal operatörler ( || && !) tarafından tetiklenir .

Boolean(2)          // explicit
if (2) { ... }      // implicit due to logical context
!!2                 // implicit due to logical operator
2 || 'hello'        // implicit due to logical operator

Not:|| and && Boole dönüşümlerini dahili olarak yapmak gibi mantıksal operatörler , ancak aslında boole olmasalar bile orijinal işlenenlerin değerini döndürür.

// returns number 123, instead of returning true
// 'hello' and 123 are still coerced to boolean internally to calculate the expression
let x = 'hello' && 123;   // x === 123

Boole dönüşümünün yalnızca 2 olası sonucu olur olmaz: doğru veya yanlış, yanlış değerlerin listesini hatırlamak daha kolaydır.

Boolean('')           // false
Boolean(0)            // false     
Boolean(-0)           // false
Boolean(NaN)          // false
Boolean(null)         // false
Boolean(undefined)    // false
Boolean(false)        // false

Listesinde olmayan herhangi bir değer dönüştürülür truedahil object, function, Array, Date, kullanıcı tanımlı türü ve benzeri. Semboller doğru değerlerdir. Boş nesne ve diziler de doğru değerlerdir:

Boolean({})             // true
Boolean([])             // true
Boolean(Symbol())       // true
!!Symbol()              // true
Boolean(function() {})  // true

Sayısal dönüşüm

Açık bir dönüşüm için, Number()işlevi Boolean()ve ile yaptığınız gibi uygulayın String().

Örtük dönüştürme aldatıcıdır, çünkü daha fazla durumda tetiklenir:

  • karşılaştırma operatörleri (>, <, <=,> =)

  • bitsel operatörler (| & ^ ~)

  • aritmetik operatörler (- + * /%). Herhangi bir işlenen bir dizge olduğunda ikili + 'nın sayısal dönüşümü tetiklemediğini unutmayın.

  • tekli + operatör

  • gevşek eşitlik operatörü == (dahil! =).

    Her iki işlenen de dize olduğunda == işlevinin sayısal dönüşümü tetiklemediğini unutmayın.

    Sayı ('123') // açık + '123' // örtük 123! = '456' // örtük 4> '5' // örtük 5 / null // örtük doğru | 0 // örtük

İlkel değerlerin sayılara nasıl dönüştürüldüğü aşağıda açıklanmıştır:

Number(null)                   // 0
Number(undefined)              // NaN
Number(true)                   // 1
Number(false)                  // 0
Number(" 12 ")                 // 12
Number("-12.34")               // -12.34
Number("\n")                   // 0
Number(" 12s ")                // NaN
Number(123)                    // 123



0
var str = 'dude';
console.log(typeof str); // "string"
console.log(!str); // false
console.log(typeof !str); // "boolean"

Başlangıçta bir dizge olarak bildirilen ve! İle boole değerine zorlanan bir değişken örneği. Şebeke


3
Lütfen cevabınızı detaylandırın. Yalnızca kod yanıtları gerçekten yardımcı olmuyor.
Cezar

3
şahsen kod örneklerini özlü, açıklayıcı ve çok faydalı buluyorum, sanırım bu kişisel bir fikir meselesi
Mister P

0

Tür zorlaması, değeri bir türden diğerine dönüştürme işlemidir (dizeden sayıya, nesneden mantıksal değere vb.). İster ilkel ister nesne olsun herhangi bir tür, tür zorlaması için geçerli bir konudur. Hatırlamak gerekirse, ilkeller şunlardır: sayı, dize, boole, null, tanımsız + Sembol (ES6'da eklenmiştir).

Tür zorlaması açık ve örtük olabilir.

Bir geliştirici, Number (değer) gibi uygun kodu yazarak türler arasında dönüştürme yapma niyetini ifade ettiğinde, buna açık tür zorlama (veya tür atama) denir.

JavaScript zayıf yazılmış bir dil olduğundan, değerler farklı türler arasında otomatik olarak dönüştürülebilir ve buna örtük tür zorlaması denir. Genellikle, 1 == null, 2 / '5', null + new Date () gibi farklı türlerdeki değerlere operatörler uyguladığınızda olur veya if (value) {… gibi çevreleyen bağlam tarafından tetiklenebilir. }, burada değer boole'ye zorlanır.

Örtük tür zorlaması için bazı örnekler:

true + false
12 / "6"
"number" + 15 + 3
15 + 3 + "number"
[1] > null
"foo" + + "bar"
'true' == true
false == 'false'
null == ''
!!"false" == !!"true"
[‘x’] == x
[] + null + 1
[1,2,3] == [1,2,3]
{}+[]+{}+[1]
!+[]+[]+![]
new Date(0) - 0
new Date(0) + 0

daha fazlasını okuyun: https://www.freecodecamp.org/news/js-type-coercion-explained-27ba3d9a2839/


-2

Veri türü birbirine eşit değilse, Zorlama Olur. 3 == "3" veya boolen == tamsayı gibi

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.