ฉันสามารถตั้งค่าตัวแปรเป็นไม่ได้กำหนดหรือผ่านไม่ได้กำหนดเป็นอาร์กิวเมนต์ได้หรือไม่?


304

ฉันสับสนเกี่ยวกับ JavaScript undefinedและnullค่า

สิ่งที่ไม่if (!testvar)จริงทำอย่างไร มันทดสอบundefinedและnullหรือเพียงแค่undefined?

เมื่อตัวแปรถูกกำหนดฉันสามารถล้างมันกลับเป็นundefined(ดังนั้นการลบตัวแปร)

ฉันสามารถส่งundefinedเป็นพารามิเตอร์ได้หรือไม่ เช่น:

function test(var1, var2, var3) {

}

test("value1", undefined, "value2");

คำตอบ:


513

ฉันสับสนเล็กน้อยเกี่ยวกับ Javascript ที่ไม่ได้กำหนด & null

nullอย่าสับสนเกี่ยวกับ โดยทั่วไปแล้วจะมีเหตุผลและมีความคล้ายคลึงกับแนวคิดของภาษาสคริปต์อื่น ๆ เกี่ยวกับออบเจ็กต์นอกขอบเขต 'โมฆะ', 'ไม่มี' หรือ 'ไม่มี'

undefinedในทางกลับกันเป็นจาวาสคริปต์ที่แปลกประหลาด nullมันเป็นวัตถุเดี่ยวที่แสดงถึงการออกจากวงของค่านิยมหลักที่สองคล้ายกัน แต่แตกต่างกัน มันเกิดขึ้น:

  1. เมื่อคุณเรียกใช้ฟังก์ชั่นที่มีการขัดแย้งน้อยกว่ารายการข้อโต้แย้งในfunctionรายการคำสั่งข้อโต้แย้ง unpassed undefinedมีการกำหนดให้ คุณสามารถทดสอบสิ่งนั้นด้วยเช่น:

    function dosomething(arg1, arg2) {
        if (arg2===undefined)
        arg2= DEFAULT_VALUE_FOR_ARG2;
        ...
    }

    ด้วยวิธีนี้คุณจะไม่สามารถบอกความแตกต่างระหว่างdosomething(1)และdosomething(1, undefined); arg2จะเป็นค่าเดียวกันทั้งคู่ หากคุณต้องการบอกความแตกต่างคุณสามารถดูได้arguments.lengthแต่การทำข้อโต้แย้งเพิ่มเติมเช่นนั้นไม่สามารถอ่านได้โดยทั่วไป

  2. เมื่อฟังก์ชั่นไม่มีreturn value;มันจะกลับundefinedมา โดยทั่วไปไม่จำเป็นต้องใช้ผลลัพธ์การส่งคืนดังกล่าว

  3. เมื่อคุณประกาศตัวแปรโดยมีvar aคำสั่งในบล็อก undefinedแต่ยังไม่ได้กำหนดค่าให้มันเป็น อีกครั้งคุณไม่จำเป็นต้องพึ่งพาสิ่งนั้นจริงๆ

  4. typeofผู้ประกอบการที่น่ากลัวกลับมา'undefined'เมื่อตัวถูกดำเนินการเป็นตัวแปรง่ายที่ไม่มีอยู่แทนที่จะโยนข้อผิดพลาดตามปกติจะเกิดขึ้นหากคุณพยายามที่จะอ้างถึง (คุณสามารถให้มันเป็นตัวแปรง่ายๆที่อยู่ในวงเล็บ แต่ไม่ใช่นิพจน์เต็มรูปแบบที่เกี่ยวข้องกับตัวแปรที่ไม่มีอยู่) ไม่ได้ใช้งานมากนักสำหรับสิ่งนั้น

  5. นี่คือข้อขัดแย้ง เมื่อคุณเข้าถึงคุณสมบัติของวัตถุที่ไม่มีอยู่คุณจะไม่ได้รับข้อผิดพลาดเช่นในภาษาอื่นทุกภาษาทันที แต่คุณจะได้รับundefinedวัตถุ (และเมื่อคุณพยายามใช้undefinedวัตถุนั้นในสคริปต์มันจะผิดไปในทางที่แปลกกว่านั้นยากที่จะติดตามมากกว่าถ้า JavaScript เพิ่งโยนข้อผิดพลาดทันที)

    มักใช้เพื่อตรวจสอบการมีอยู่ของคุณสมบัติ:

    if (o.prop!==undefined) // or often as truthiness test, if (o.prop)
       ...do something...

    อย่างไรก็ตามเนื่องจากคุณสามารถกำหนดundefinedเช่นเดียวกับค่าอื่น ๆ :

    o.prop= undefined;

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

    if ('prop' in o)
        ...

โดยสรุปundefinedเป็นระเบียบเฉพาะ JavaScript ซึ่งสร้างความสับสนให้ทุกคน นอกเหนือจากอาร์กิวเมนต์ฟังก์ชันที่เป็นตัวเลือกที่ JS ไม่มีกลไกหรูหราอื่น ๆundefinedควรหลีกเลี่ยง ไม่ควรเป็นส่วนหนึ่งของภาษา nullจะทำงานได้ดีสำหรับ (2) และ (3) และ (4) เป็นความผิดพลาดที่มีอยู่เพียงเพราะใน JavaScript เริ่มต้นไม่มีข้อยกเว้น

สิ่งที่ไม่if (!testvar)จริงทำอย่างไร มันทดสอบสำหรับไม่ได้กำหนดและเป็นโมฆะหรือเพียงแค่ไม่ได้กำหนด?

เช่น 'truthiness' การตรวจสอบการทดสอบกับfalse, undefined, null, 0, NaNและสตริงที่ว่างเปล่า แต่ในกรณีนี้ใช่มันเป็นเรื่องที่undefinedเกี่ยวข้องจริงๆ IMO if (testvar!==undefined)มันควรจะเป็นมากขึ้นอย่างชัดเจนเกี่ยวกับที่และการพูด

เมื่อตัวแปรถูกกำหนดฉันสามารถล้างมันกลับเป็น undefined (ดังนั้นการลบตัวแปร)

คุณสามารถกำหนดให้undefinedกับมันได้อย่างแน่นอนแต่นั่นจะไม่ลบตัวแปร มีเพียงdelete object.propertyผู้ให้บริการเท่านั้นที่จะลบสิ่งต่าง ๆ

deleteมีความหมายจริงๆสำหรับคุณสมบัติมากกว่าตัวแปรเช่นนี้ เบราว์เซอร์จะช่วยให้คุณหนีออกไปได้อย่างอิสระdelete variableแต่ไม่ใช่ความคิดที่ดีและจะไม่ทำงานในโหมดที่เข้มงวดของ ECMAScript Fifth Edition หากคุณต้องการเพิ่มการอ้างอิงถึงบางสิ่งบางอย่างเพื่อให้สามารถรวบรวมขยะvariable= nullได้

ฉันจะส่งผ่านไม่ได้กำหนดเป็นพารามิเตอร์ได้หรือไม่

ใช่.


10
ช่างเป็นคำตอบที่วิเศษมาก ฉันล้มเหลวในการทดสอบ JavaScript: perfectionkills.com/javascript-quiz ภายหลังฉันจะอ่านคำตอบของคุณอีกครั้งและลองทดสอบอีกครั้ง!
Skilldrick

1
คงที่, ta. (ฉันมักจะไม่กังวลมากเกินไปเกี่ยวกับการมอบหมายใหม่เนื่องจากมีหลายสิ่งหลายอย่างที่สคริปต์สามารถกำหนดใหม่เพื่อทำให้ยุ่งเหยิงทุกอย่างจนกรณีทั่วไปเป็นไปไม่ได้ที่จะแก้ไข)
bobince

2
@bince undefinedเป็นวัตถุเดี่ยวหรือไม่ คุณหมายถึงอะไร มันเป็นค่าดั้งเดิมไม่ใช่วัตถุ
Šime Vidas

2
@Hortitude: นั่นเป็นจุด (4) โดยทั่วไปฉันจะไม่typeof foo=='undefined'; ก็มีแนวโน้มที่จะใช้สำหรับ (4A) ทั่วโลกดมกลิ่นซึ่งในกรณีนี้ฉันชอบที่จะมีความชัดเจนและพูด'foo' in windowหรือ (4b) การทดสอบกับundefined-value foo===undefinedตัวเองซึ่งในกรณีนี้ฉันไม่ต้องการที่จะอ่านและการพูด ในทางทฤษฎีการทดสอบtypeofกับ'undefined'อาจมีกรณีการใช้งานที่สร้างอื่น ๆ ที่ไม่สามารถให้: ดมกลิ่นเพื่อการดำรงอยู่ของตัวแปรท้องถิ่น อย่างไรก็ตามในความเป็นจริงคุณรู้อยู่เสมอว่ามีการประกาศตัวแปรใดบ้าง
bobince

4
หนึ่ง caveat กับ # 2 มักจะเป็นฟังก์ชั่นที่ไม่มีreturnคำสั่งส่งกลับundefinedแต่ถ้าฟังก์ชั่นเป็นคอนสตรัค (เรียกใช้กับnewผู้ประกอบการ) มันจะกลับมาวัตถุใหม่ (มูลค่าของคอนthisสตรัคเตอร์) แม้จะไม่มีreturnคำสั่ง ผลตอบแทน console.log((function (){}())); ส่งคืนวัตถุ undefinedconsole.log((new function (){}()));
รหัสที่ไร้ประโยชน์

18

คุณไม่สามารถ (ไม่ควร?) กำหนดสิ่งที่ไม่ได้กำหนดเนื่องจากตัวแปรจะไม่ถูกกำหนดอีกต่อไป - คุณเพิ่งกำหนดให้กับบางสิ่ง

คุณไม่สามารถส่งผ่านundefinedไปยังฟังก์ชั่น หากคุณต้องการส่งผ่านค่าว่างให้ใช้nullแทน

คำสั่งif(!testvar)การตรวจสอบสำหรับค่าจริง / เท็จบูลีนนี้โดยเฉพาะไม่ว่าจะเป็นหนึ่งในการทดสอบประเมินtestvar falseตามคำจำกัดความnullและundefinedไม่ควรถูกประเมินว่าไม่ใช่trueหรือfalseแต่ JavaScript ประเมินnullว่าเป็นfalseและให้ข้อผิดพลาดหากคุณพยายามประเมินตัวแปรที่ไม่ได้กำหนด

ในการทดสอบอย่างเหมาะสมundefinedหรือnullใช้สิ่งเหล่านี้:

if(typeof(testvar) === "undefined") { ... }

if(testvar === null) { ... }

1
สามเท่าจะตรวจสอบประเภทเช่นกันดังนั้นจึงไม่มีการบีบบังคับประเภท ดักลาสคร็อคฟอร์ดแนะนำว่าไม่ควรใช้ตัวดำเนินการพิมพ์ดีด ( ==และ!=)
Skilldrick

3
คุณสามารถกำหนดสิ่งที่ไม่ได้กำหนด var a= undefined. fn(undefined)คุณสามารถส่งผ่าน หากคุณต้องการหาความแตกต่างระหว่างคุณสมบัติที่ไม่ได้กำหนดpของวัตถุoและคุณสมบัติpที่ได้กำหนดและตั้งค่าไว้undefinedคุณจะต้องใช้'p' in oโอเปอเรเตอร์
bobince

1
มีเหตุผลทำไมไม่ควรทดสอบtestvar === undefinedแทนที่จะซับซ้อนกว่าtypeof(testvar) === "undefined"หรือไม่?
ddaa

4
มีอีกเหตุผลที่ดีสำหรับการใช้เป็นtypeofทดสอบตัวแปรไม่ได้กำหนด: แตกต่างnull, undefinedเป็นเพียงคุณสมบัติของวัตถุโลกและตัวเองอาจจะนิยามใหม่ ใช้รูปแบบการเข้ารหัสเฉพาะและเครื่องหมายเท่ากับที่หายไปเท่านั้นและundefinedมีการเปลี่ยนแปลงอย่างเงียบ ๆ :if (undefined = someVar) {...}
Tim Down

1
@IanGrainger: ECMAScript 5 (มีการใช้งานในเบราว์เซอร์ทุกเวอร์ชันปัจจุบัน) ส่วนใหญ่จะแก้ไขปัญหานี้โดยการสร้างundefinedคุณสมบัติที่ไม่เปลี่ยนรูปแบบของวัตถุระดับโลกดังนั้นจึงปลอดภัยกว่าที่เคยเป็น อย่างไรก็ตามยังคงเป็นไปได้ที่จะกำหนดตัวแปรที่ไม่แน่นอนที่เรียกว่าundefinedภายในฟังก์ชั่นดังนั้นปัญหายังไม่หายไปทั้งหมด
Tim Down

13

ความแตกต่างพื้นฐานคือundefinedและnullแสดงแนวคิดที่แตกต่าง

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

var a;

a == null; // This is true
a == undefined; // This is true;
a === undefined; // This is true;

อย่างไรก็ตามหากคุณตั้งใจตั้งค่าnullความเท่าเทียมอย่างเข้มงวดกับความundefinedล้มเหลวจึงช่วยให้คุณสามารถแยกความแตกต่างระหว่างnullและundefinedค่า:

var b = null;
b == null; // This is true
b == undefined; // This is true;
b === undefined; // This is false;

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

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined

ลักษณะการทำงานนี้ไม่ได้เฉพาะเจาะจงกับ JavaScript และเสร็จสิ้นแนวคิดทั่วไปที่ผลบูลสามารถtrue, falseไม่รู้จัก ( null) ไม่มีค่า ( undefined) หรือสิ่งที่ผิดพลาด ( error)

http://en.wikipedia.org/wiki/Undefined_value


และยังคง nullทำงานได้ดี a == nullเป็นtrueเพราะการบังคับประเภทจาวาสคริปต์
sleepwalkerfx

11

วิธีที่ดีที่สุดในการตรวจสอบค่า Null คือ

if ( testVar !== null )
{
    // do action here
}

และสำหรับไม่ได้กำหนด

if ( testVar !== undefined )
{
    // do action here
}

คุณสามารถกำหนด avariable ด้วย undefined

testVar = undefined;
//typeof(testVar) will be equal to undefined.

1
วิธีที่ดีที่สุดในการตรวจสอบค่า Null คือการใช้!==ไม่ใช่!=
MBO

6

ใช่คุณสามารถทำได้เนื่องจากไม่ได้กำหนดถูกกำหนดเป็นไม่ได้กำหนด

console.log(
   /*global.*/undefined === window['undefined'] &&
   /*global.*/undefined === (function(){})() &&
   window['undefined']  === (function(){})()
) //true

กรณีของคุณ:

test("value1", undefined, "value2")

คุณยังสามารถสร้างตัวแปรที่ไม่ได้กำหนดของคุณเอง:

Object.defineProperty(this, 'u', {value : undefined});
console.log(u); //undefined

5

เพื่อตอบคำถามแรกของคุณตัวดำเนินการไม่ใช่ ( !) จะรวมกันเป็นค่าใดก็ได้ที่ระบุไว้ในค่าบูลีน ดังนั้นnull, 0, false, NaNและ""(สตริงว่าง) จะปรากฏเท็จ


และยังมีสตริงว่างและ NaN (ไม่ใช่ตัวเลข)
MBO

undefinedจะไม่ปรากฏขึ้นเนื่องจากfalseจะมีข้อผิดพลาด 'ไม่ได้กำหนดไว้'
Tatu Ulmanen

Tatu Ulmanen: ไม่จริง if (undefined) {/* Do stuff*/}จะไม่ให้ข้อผิดพลาดเนื่องจากundefinedมีอยู่เป็นคุณสมบัติของวัตถุทั่วโลก สิ่งที่จะทำให้เกิดข้อผิดพลาดคือสิ่งที่ต้องการif (someUndeclaredVariable) {/* Do stuff*/}
Tim Down

2

JavaScript, วิธีการตั้งค่าตัวแปรเป็น undefined บน commandline:

ตั้งค่าตัวแปรเป็น undefined ในjsเทอร์มินัลบรรทัดคำสั่ง javascript ที่มาพร้อมกับ Java บน Ubuntu 12.10

el@defiant ~ $ js

js> typeof boo
"undefined"

js> boo
typein:2: ReferenceError: boo is not defined

js> boo=5
5

js> typeof boo
"number"

js> delete(boo)
true

js> typeof boo
"undefined"

js> boo
typein:7: ReferenceError: boo is not defined

หากคุณตั้งค่าตัวแปรเป็นไม่ได้กำหนดในจาวาสคริปต์:

ใส่ไว้ใน myjs.html:

<html>
<body>
    <script type="text/JavaScript">
        document.write("aliens: " + aliens);
        document.write("typeof aliens: " + (typeof aliens));
        var aliens = "scramble the nimitz";
        document.write("found some aliens: " + (typeof aliens));
        document.write("not sayings its aliens but... " + aliens);
        aliens = undefined;
        document.write("aliens deleted");
        document.write("typeof aliens: " + (typeof aliens));
        document.write("you sure they are gone? " + aliens);
    </script>
</body>
</html>

มันพิมพ์สิ่งนี้:

aliens: undefined
typeof aliens: undefined
found some aliens: string
not sayings its aliens but... scramble the nimitz
aliens deleted
typeof aliens: undefined
you sure they are gone? undefined

คำเตือน! เมื่อตั้งค่าตัวแปรของคุณเป็นไม่ได้กำหนดคุณกำลังตั้งค่าตัวแปรของคุณเป็นตัวแปรอื่น หากมีคนลับๆล่อๆทำงานundefined = 'rm -rf /';เมื่อใดก็ตามที่คุณตั้งค่าตัวแปรของคุณเป็นไม่ได้กำหนดคุณจะได้รับค่านั้น

คุณอาจสงสัยว่าฉันจะสามารถส่งออกเอเลี่ยนค่าที่ไม่ได้กำหนดได้อย่างไรในตอนเริ่มต้นและมันยังคงทำงานอยู่ เป็นเพราะการใช้ javascript hoisting: http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html



0

สำหรับif (something)และif (!something)มักใช้เพื่อตรวจสอบว่ามีการกำหนดหรือไม่กำหนด ตัวอย่างเช่น:

if (document.getElementById)

ระบุจะถูกแปลงเป็นค่าบูลีนจึงถูกตีความว่าเป็นundefined falseแน่นอนว่ามีค่าอื่น ๆ (เช่น 0 และ '') ที่ตีความเช่นfalseกัน แต่ตัวระบุไม่ควรมีค่าเช่นนี้อย่างสมเหตุสมผลหรือคุณมีความสุขกับการรักษาค่าเช่นเดียวกับที่ไม่ได้กำหนด

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

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


0

เพื่อความสนุกนี่เป็นวิธีที่ค่อนข้างปลอดภัยในการกำหนด "ไม่ได้กำหนด" ให้กับตัวแปร สำหรับสิ่งนี้ที่จะมีการชนกันจะต้องมีใครบางคนที่จะเพิ่มไปยังต้นแบบสำหรับวัตถุที่มีชื่อเดียวกันกับสตริงที่สร้างแบบสุ่ม ฉันแน่ใจว่าตัวสร้างสตริงแบบสุ่มสามารถปรับปรุงได้ แต่ฉันเอามาจากคำถามนี้: สร้างสตริง / ตัวอักษรแบบสุ่มใน JavaScript

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

function GenerateRandomString() {
    var text = "";
    var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

    for (var i = 0; i < 50; i++)
        text += possible.charAt(Math.floor(Math.random() * possible.length));

    return text;
}

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