JavaScript เป็นภาษาที่ไม่ได้พิมพ์หรือไม่?


104

ฉันพบว่ามีบางคนเรียก JavaScript ว่าเป็นภาษา "แบบไดนามิกและพิมพ์ผิด" แต่บางคนถึงกับพูดว่า "ไม่พิมพ์"? ซึ่งจริงๆแล้ว?

คำตอบ:


133

JavaScript ไม่ได้พิมพ์ :


(ที่มา: no.gd )

แม้แต่ Brendan Eich ก็พูดเช่นนั้น ใน Twitter เขาตอบกระทู้ที่เชื่อมโยงกับคำถามนี้:

... ประเภทวิชาการใช้ "untyped" แปลว่า "no static types" ...

ดังนั้นปัญหาคือว่ามีคำจำกัดความที่แตกต่างกันไม่กี่untyped

มีการพูดถึงคำจำกัดความหนึ่งคำในหนึ่งในคำตอบข้างต้น - รันไทม์ไม่ได้แท็กค่าและถือว่าแต่ละค่าเป็นบิต JavaScript ทำค่าแท็กและมีลักษณะการทำงานที่แตกต่างกันตามแท็กเหล่านั้น เห็นได้ชัดว่า JavaScript ไม่เหมาะกับหมวดหมู่นี้

คำจำกัดความอื่น ๆ มาจากProgramming Language Theory (สิ่งทางวิชาการที่ Brendan อ้างถึง) ในโดเมนนี้untypedเพียงหมายถึงทุกอย่างที่เป็นชนิดเดียว

ทำไม? เนื่องจากภาษาจะสร้างโปรแกรมก็ต่อเมื่อสามารถพิสูจน์ได้ว่าประเภทสอดคล้องกัน (aka the Curry-Howard การโต้ตอบประเภทคือทฤษฎีบทโปรแกรมเป็นเครื่องพิสูจน์) ซึ่งหมายความว่าในภาษาที่ไม่ได้พิมพ์:

  1. โปรแกรมจะถูกสร้างขึ้นเสมอ
  2. ประเภทจึงตรงกันเสมอ
  3. จึงต้องมีเพียงชนิดเดียว

ตรงกันข้ามกับภาษาที่พิมพ์:

  1. โปรแกรมอาจจะไม่ถูกสร้างขึ้น
  2. เนื่องจากประเภทอาจไม่ตรงกัน
  3. เนื่องจากโปรแกรมสามารถมีได้หลายประเภท

ดังนั้นมีคุณไปใน PLT, untypedเพียงวิธีการพิมพ์แบบไดนามิกและการพิมพ์เพียงหมายถึงการพิมพ์แบบคงที่ JavaScript ไม่ถูกพิมพ์ในหมวดหมู่นี้อย่างแน่นอน

ดูสิ่งนี้ด้วย:


6
และแน่นอนว่า "ไม่มีประเภทคงที่" ก็ไม่เหมือนกับ "ไม่มีการประกาศประเภท" เช่นกัน
Andreas Rossberg

+1. คุณควรเชื่อมโยงสิ่งนี้ในคำตอบของคุณด้วย ข้อความ "พิมพ์ผิด" นี้แพร่หลายเกินไป
missingfaktor

2
ทฤษฎีภาษาโปรแกรมถูกต้อง ภาพหน้าจอขนาดยักษ์ไม่ถูกต้อง
Alex W

2
ฉันดีใจที่เห็นว่าคำตอบนี้อ้างอิงถึงบล็อกโพสต์ของ Harperแต่คงจะดีไม่น้อยหากชุมชน PLT ทิ้ง "ไม่ได้พิมพ์" เพื่อสนับสนุน "unityped" คำจำกัดความของ "ไม่ได้พิมพ์" หมายถึง "เพียงบิต" นั้นสมเหตุสมผลจริงๆ ในการใช้ "ไม่ได้พิมพ์" เพื่ออธิบายภาษาที่มีข้อกำหนดอย่างเป็นทางการใช้คำว่า "type" และบอกว่ามี 7 ประเภท (Undefined, Null, Number, String, Boolean, Symbol และ Object) เป็นเรื่องที่น่าสับสน คนส่วนใหญ่ไม่ต้องการแยกความคิดประเภทนี้ออกจาก PLT def
Ray Toal

4
ของคุณ1. 2. 3.สำหรับภาษา untyped ไม่ตรงกับ JavaScript ไม่ได้มีเพียงประเภทเดียว - มีประมาณ 4 - 5 ดังนั้นการสาธิต JavaScript จึงไม่ถูกพิมพ์อย่างไร?
Don Cheadle

82

แข็งแรง / อ่อนแอ สามารถคิดได้โดยสัมพันธ์กับวิธีที่คอมไพเลอร์จัดการกับการพิมพ์

  • พิมพ์ผิดหมายความว่าคอมไพเลอร์ถ้ามีไม่บังคับให้พิมพ์ถูกต้อง หากไม่มีคำอุทานคอมไพเลอร์โดยนัยคำสั่งจะผิดพลาดระหว่างรันไทม์

    "12345" * 1 === 12345  // string * number => number

    พิมพ์ขอหมายถึงมีความเป็นคอมไพเลอร์และมันต้องการให้คุณโยนอย่างชัดเจนจากสตริงเพื่อจำนวนเต็ม

    (int) "12345" * 1 === 12345

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

    ป่านนี้ JavaScript สามารถจัดประเภทเป็น Not-Strongly-Typed นั่นหมายความว่ามันพิมพ์ผิดหรือไม่ได้พิมพ์

ไดนามิก / คงที่ สามารถคิดได้โดยสัมพันธ์กับวิธีการที่คำสั่งภาษาจัดการกับประเภทต่างๆ

  • การพิมพ์แบบไดนามิกหมายถึงประเภทของค่าถูกบังคับใช้ แต่ตัวแปรเพียงแค่แทนค่าประเภทใดก็ได้

    x = 12345;    // number
    x = "string"; // string
    x = { key: "value" }; // object
    y = 123 + x; // error or implicit conversion must take place.

    การพิมพ์แบบคงที่หมายถึงประเภทตัวแปรถูกบังคับใช้อย่างมากและประเภทค่าจะถูกบังคับใช้น้อย

    int x = 12345; // binds x to the type int
    x = "string";  // too late, x is an integer - error
    string y = 123; // error or implicit conversion must take place.

    ป่านนี้ JavaScript สามารถจัดประเภทเป็น Not-Statically-Typed ได้ นอกจากนี้ดูเหมือนว่าจะพิมพ์แบบไดนามิกหากพิมพ์เลย ดังนั้นเราต้องดูว่าการพิมพ์หมายถึงอะไร

พิมพ์วิธีการที่แตกต่างระหว่างภาษาที่แตกต่างกันเช่นสตริง ,จำนวน ,บูล ,วัตถุ ,อาเรย์ , null , undefinedและอื่น ๆ นอกจากนี้การดำเนินการแต่ละอย่างจะถูกผูกไว้กับประเภทเฉพาะ คุณจึงไม่สามารถหารจำนวนเต็มด้วยสตริงได้

    2 / "blah"  // produces NaN

untypedหมายถึงการดำเนินงานของการหารจำนวนเต็มโดยสตริงจะส่งผลในการรักษาสี่ไบต์แรกของสตริงเป็นจำนวนเต็ม เนื่องจากการดำเนินการที่ไม่ได้พิมพ์เกิดขึ้นโดยตรงบนบิตจึงไม่มีประเภทที่ต้องสังเกต ผลลัพธ์จะเป็นสิ่งที่ไม่คาดคิด:

    2 / "blah"  // will be treated as  2 / 1500275048

เนื่องจาก JavaScript ทำงานตามคำจำกัดความของการพิมพ์จึงต้องเป็น ดังนั้นจึงต้องพิมพ์แบบไดนามิกและพิมพ์ผิดปกติ

หากมีใครอ้างว่า JavaScript ไม่ได้พิมพ์เป็นเพียงทฤษฎีทางวิชาการไม่ใช่เพื่อการประยุกต์ใช้งานจริง


1
แต่ฉันคิดว่ามีความขัดแย้งในคำสั่งสุดท้าย ใน JavaScript ผลลัพธ์ของการหารสตริงจำนวนเต็มถูกกำหนดไว้อย่างดีสำหรับค่าใด ๆ ของจำนวนเต็มหรือสตริง มันไม่มีประโยชน์มาก!
Deniz Dogan

หากคุณมีคำจำกัดความ / คำอธิบายที่ดีกว่านี้อย่าลังเลที่จะแก้ไข นั่นเป็นเหตุผลที่ฉันตั้งเป็นวิกิชุมชน
Gumbo

@skurpur: คุณได้เปลี่ยนความหมายของ Dynamic และ Weak อย่างสมบูรณ์ - แก้ไขสิ่งนั้น
Rene Saarsoo

ขออภัยคุณแก้ไขในขณะที่ฉันกำลังแก้ไขและฉันเขียนทับการเปลี่ยนแปลงของคุณ
Rene Saarsoo

3
-1. คุณจะต้องอ่านนี้
missingfaktor

48

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

โปรดทราบว่า JavaScript ถูกพิมพ์แบบไดนามิกด้วยเช่นกัน วิธีการนี้จะช่วยให้การพิมพ์สิ่งที่เป็นความรู้เป็น"เป็ดพิมพ์"

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


2
-1. คุณจะต้องอ่านนี้
missingfaktor

4
คำตอบนี้ดีกว่ามากและแม่นยำกว่าคำตอบที่ได้รับการโหวตสูงสุด
Alex W

3
@JimboJonny: ไม่ถูกต้อง เว้นเสียแต่ว่าต่อหน้าผู้พัฒนาแอสเซมบลีมันจะไม่ผิดเกินไปที่จะระบุว่าทุกภาษาถูกพิมพ์ Untyped หมายถึงการดำเนินการเดียวที่ดำเนินการโดยตรงกับการจัดการบิต แต่ให้พิจารณาว่า Javascript มี toString () และ parseInt () เมธอด อย่าพิมพ์มากไปกว่านั้น
Suamere

2
@Suamere - นี่คือคำพูดจาก“ Javascript: The Definitive Guide”จาก O'Reilly: “ ความแตกต่างที่สำคัญระหว่าง JavaScript และภาษาเช่น Java และ C คือ JavaScript ไม่ได้พิมพ์ ซึ่งหมายความว่าในบางส่วนตัวแปร JavaScript สามารถเก็บค่าของประเภทข้อมูลใด ๆ ซึ่งแตกต่างจากตัวแปร Java หรือ C ซึ่งสามารถเก็บข้อมูลได้เพียงประเภทเดียวเท่านั้นที่มีการประกาศ "
Jimbo Jonny

3
ดังนั้นหากคุณซื้อใน BS ที่เพื่อนบางคนอ้างว่านักวิชาการจงใจใช้คำว่า "ไม่พิมพ์" เพื่อหมายถึง "พิมพ์แบบไดนามิก" ใช่แล้ว JavaScript ไม่ได้ถูกพิมพ์โดยการพิสูจน์ของคุณทั้งหมด แต่ถ้าคุณรู้ว่า " ไม่ได้พิมพ์" ถูกใช้อย่างไม่ถูกต้องเพื่อแสดงถึงภาษาที่ "พิมพ์แบบไดนามิก" อย่างแท้จริงให้เรียกภาษาดังกล่าวว่า "พิมพ์แบบไดนามิก" tinyurl.com/czhcv54
Suamere

8

ไปยังจุดที่ผู้เขียน JavaScript ยังจัดเป็นแบบไดนามิกพิมพ์ Wiki ระบุว่าภาษาที่พิมพ์แบบไดนามิกจะถูกตรวจสอบที่รันไทม์แทนที่จะเป็นในคอมไพเลอร์ในขณะที่ Weakly Typed หมายถึงความสามารถในการเปลี่ยนประเภทได้ทันทีภายในโค้ดของคุณ ใช่มันเป็นทั้งแบบไดนามิกและพิมพ์อ่อนแอ


6

ปัญหาที่สร้างความสับสนให้กับโปรแกรมเมอร์จำนวนมากคือคำจำกัดความเช่นนี้ไม่ได้มาตรฐาน คำว่าภาษาโปรแกรมที่ไม่พิมพ์มีความคลุมเครือ นั่นหมายถึงภาษาที่ไม่มีชนิดข้อมูลหรือภาษาที่เป็นตัวแปรที่ไม่มีการพิมพ์แคลคูลัสแลมบ์ดาหรือไม่?

JavaScript / ECMAScript มีระบบประเภทและโดเมนของฟังก์ชันทั้งหมดจะยอมรับประเภทข้อกำหนดอ้างอิงใด ๆ นั่นหมายความว่า JavaScript มีประเภทข้อมูลเดียวในความเป็นจริง นั่นเป็นเรื่องของการนำไปใช้งานที่มีความสำคัญมากกว่าสำหรับโปรแกรมเมอร์ JavaScript ขั้นสูง โปรแกรมเมอร์ JavaScript โดยเฉลี่ยสนใจเฉพาะประเภทข้อมูลภาษานามธรรม ที่ ECMAScript ระบุเท่านั้น

ในบริบทของโปรแกรมเมอร์ในชีวิตประจำวันไม่ได้เป็นนักวิจัยหรือนักวิทยาศาสตร์คอมพิวเตอร์ทฤษฎีคำว่าuntypedคือการเรียกชื่อผิดเพราะคนส่วนใหญ่ไม่ได้ทำแคลคูลัสแลมบ์ดา ดังนั้นคำนี้สร้างความสับสนให้กับมวลชนและดูเหมือนว่าจะประกาศว่า JavaScript ไม่มีประเภทข้อมูลใด ๆ ซึ่งไม่เป็นความจริง ทุกคนที่เคยใช้จะtypeofรู้ว่า JavaScript มีประเภทข้อมูลภาษาของตัวเอง:

var test = "this is text";
typeof(test);

ผลตอบแทน

"สตริง"

ECMAScript กำหนดประเภทต่อไปนี้สำหรับภาษา: undefined, null, string, boolean, number,object

http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf

การกำหนดที่แม่นยำยิ่งขึ้นสำหรับ JavaScript จะเป็นการพิมพ์โดยปริยายพิมพ์แบบไดนามิกหรือพิมพ์อย่างอ่อน / หลวม (หรือรวมกันบางอย่าง) ใน JavaScript นั้นใช้การบังคับประเภทในบางกรณีซึ่งทำให้ประเภทมีนัยเนื่องจากคุณไม่จำเป็นต้องระบุอย่างชัดเจน ประเภทของตัวแปรของคุณ มันอยู่ภายใต้การพิมพ์ที่อ่อนแอเนื่องจากไม่เหมือนกับภาษาบางภาษาที่แยกความแตกต่างระหว่างnumberจำนวนทศนิยมและจำนวนเต็ม ฯลฯ เพียงแค่ใช้ประเภทเดียวเพื่อรวมตัวเลขทั้งหมดและใช้การบังคับประเภทที่กล่าวถึงก่อนหน้านี้[มาตรา 9 ของ ECMAScript Spec]ซึ่งตรงกันข้ามกับ a ภาษาที่พิมพ์ยากซึ่งจะมีประเภทข้อมูลที่เฉพาะเจาะจงมาก (เช่นคุณจะต้องระบุintหรือfloat)

คำจำกัดความของภาษาที่พิมพ์แบบคงที่และแบบไดนามิกนั้นไม่ได้เป็นมาตรฐานอย่างไรก็ตามทั้งสองก็ไม่มีขนาดของไบต์เมื่อคอมพิวเตอร์เริ่มมีวิวัฒนาการ การพิมพ์แบบคงที่และแบบไดนามิกส่วนใหญ่มักอ้างถึงคุณสมบัติของภาษาบางอย่าง ซึ่งเป็นหนึ่งในประเภทของการตรวจสอบที่รันไทม์หรือสิ่งที่เรียกว่าแบบไดนามิกประเภทการตรวจสอบ หากคุณเคยใช้ JavaScript คุณรู้อยู่แล้วว่าต้องรอจนกว่ารันไทม์จะตรวจสอบประเภทซึ่งเป็นสาเหตุที่คุณได้รับTypeErrorข้อยกเว้นระหว่างการเรียกใช้โค้ดของคุณ ตัวอย่างที่นี่

ผมคิดว่าด้านบนลงคะแนนคำตอบที่เป็นความสับสนpolymorphism ฟังก์ชัน JavaScriptที่มีฟังก์ชั่นที่จะยอมรับอะไร (เช่นเดียวกับสายพันธุ์ untyped ของแลมบ์ดาแคลคูลัส) อย่างแท้จริงซึ่งเป็นสมาคมการเข้าใจผิด


ไม่ใช่การเรียกชื่อผิด แต่บริบทมีความสำคัญโปรดดูstackoverflow.com/questions/9154388/…
Andreas Rossberg

@AndreasRossberg มันอย่างแน่นอนคือการเรียกชื่อผิด สิ่งที่คุณอ้างถึงในลิงก์ที่โปรโมตตัวเองอย่างไร้ยางอายคือระบบประเภท เหตุผลที่คำนี้เป็นการเรียกชื่อผิดเพราะมีความคลุมเครือ โปรแกรมเมอร์ส่วนใหญ่คิดว่าข้อมูลที่พิมพ์ไม่พิมพ์ระบบเมื่อพวกเขาได้ยินเกี่ยวกับภาษา untyped ฉันคิดว่าความคิดเห็นของ Konrad Rudophผลักดันประเด็นนี้ให้กลับบ้านจริงๆ
Alex W

ไม่แน่ใจว่าทำไมคุณถึงคิดว่า "ไร้ยางอาย" เพื่ออ้างถึงคำตอบก่อนหน้าของฉันแทนที่จะพูดซ้ำที่นี่ นอกจากนี้ฉันพูดอย่างชัดเจนว่าบริบทมีความสำคัญ ตรงกันข้ามกับคำร้องเรียนของ K. รูดอล์ฟมีคำจำกัดความที่สอดคล้องกันอย่างสมบูรณ์และเป็นที่ยอมรับอย่างกว้างขวางเกี่ยวกับ "ระบบประเภท" ในวรรณกรรมและฉันได้ยกมาคำหนึ่ง แน่นอนว่าคุณมีอิสระที่จะพบว่าพวกเขาสับสนในบริบทของคุณ แต่นั่นไม่ได้ทำให้พวกเขา "เรียกชื่อผิด"
Andreas Rossberg

@AndreasRossberg Context มีความสำคัญมากที่นี่ คำตอบที่ได้รับการโหวตสูงสุดระบุว่า "untyped = no type declarations" ซึ่งไม่ถูกต้องอย่างชัดเจน สิ่งที่ฉันกำลังพูดคือมันเป็นการเรียกชื่อผิดในบริบทนี้ ไม่มีใครพูดถึงแคลคูลัสแลมบ์ดาที่นี่และการทำเช่นนั้นค่อนข้างอวดดีในกรณีง่ายๆนี้
Alex W

1

โปรดจำไว้ว่า JavaScript ช่วยให้คุณสามารถขอให้สิ่งที่เป็นtypeof(your_variable)และเปรียบเทียบประเภทผลตอบแทน5==="5" falseฉันไม่คิดว่าคุณจะเรียกมันว่าไม่พิมพ์ได้

เป็นแบบไดนามิกและ (ประมาณว่า) พิมพ์ผิด คุณอาจต้องการทราบว่ามันใช้การพิมพ์เป็ด (ดูลิงก์ของแอนดรูว์) และเสนอ OOP ผ่านการสร้างต้นแบบแทนการเรียนและการสืบทอด


การพิมพ์ตัวแปรไม่มีส่วนเกี่ยวข้องกับการส่งค่า เกี่ยวข้องกับการประกาศประเภทของตัวแปร Javascript ไม่มีโครงสร้างสำหรับสิ่งนี้เลยซึ่งเป็นสาเหตุที่มีนักเขียนจาวาเพียงไม่กี่คนที่เข้าใจแนวคิดนี้และเหตุใดหลายคนจึงเข้าใจผิดว่าการพิมพ์ตัวแปรเป็นสิ่งที่เกี่ยวข้องกับการเปรียบเทียบหรือการแคสต์ประเภทตัวแปร ใน JS คุณไม่สามารถประกาศString a = "blah";หรือvar a:String = 'blah';(เช่นตัวแปรที่พิมพ์) ได้เลย นั่นคือเหตุผลที่ไม่ได้พิมพ์
Jimbo Jonny

0

ในขณะที่พิมพ์อยู่ (คุณสามารถถาม "typeof someVar" และเรียนรู้ประเภทเฉพาะของมันได้ แต่มันก็อ่อนแอมาก

ให้:

  var a = "5";

คุณอาจบอกว่า a คือสตริง อย่างไรก็ตามหากคุณเขียน:

  var b = a + 10;

b คือ int เท่ากับ 15 ดังนั้นการกระทำก็เหมือนกับ int แน่นอนคุณสามารถเขียน:

  var c = a + "Hello World";

และ c จะเท่ากับ "5Hello World" ดังนั้น a จึงทำหน้าที่เหมือนสตริงอีกครั้ง


1) การแคสต์ค่า! = การพิมพ์ตัวแปร 2) มันไม่ได้อ่อนแอไม่มีอยู่จริง คุณไม่สามารถพิมพ์ตัวแปรในจาวาสคริปต์
Jimbo Jonny

สงสัยว่าทำไมคำตอบนี้ถึงได้รับสองคะแนน คำจำกัดความที่ฉันพบในการพิมพ์ที่อ่อนแอกล่าวได้อย่างแม่นยำ: ประเภทของค่าจะถูกกำหนดตามวิธีการใช้งาน
aioobe

ข้อมูลนี้ถูกต้องหรือไม่? ฉันจะได้bเท่ากับ510: ideone.com/BRcSW7
aioobe
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.