Tốt hơn là trả về ʻundefined` hoặc `null` từ một hàm javascript?


98

Tôi có một hàm mà tôi đã viết về cơ bản trông như thế này:

function getNextCard(searchTerms) {
  // Setup Some Variables

  // Do a bunch of logic to pick the next card based on termed passed through what I'll call here as 'searchTerms' all of this logic is omitted because it's not important for my question.
  // ...

  // If we find a next card to give, than give it
  if (nextCardFound)
    return nextCardFound;

  // Otherwise - I'm returning undefined
  return undefined;
}

Câu hỏi: Sẽ tốt hơn nếu trả về "null" ở đây?

Tôi có thể trả lại bất cứ thứ gì tôi muốn - rõ ràng là ... tôi chỉ không chắc đâu là thứ tốt nhất để sử dụng.

Mã gọi hàm này biết cách xử lý với undefined (nó thực sự sẽ không bao giờ thực sự xảy ra trừ khi có sự cố khủng khiếp)

Lý do tôi hỏi câu hỏi này là tôi đã nghe ở đâu đó một điều gì đó giống như "Đừng gán giá trị không xác định cho các biến" hoặc điều gì đó - điều đó sẽ khiến việc gỡ lỗi trở nên khó khăn hơn. Vì vậy, thực tế là tôi có thể thấy rằng nullđược trả về cho tôi biết rằng trả về đang hoạt động - nhưng về cơ bản hoạt động tương tự như undefined.


Tài liệu:

Mozilla Docs Không trả lời câu hỏi của tôi ... google cũng không: \

Câu hỏi SO này - quá rộng so với những gì tôi đang cố gắng tìm ra ở đây.


1
câu hỏi này không câu trả lời SO ?
warkentien2

8
Theo tôi, hãy trở về null. Để lại undefinedcho chính JavaScript. Tuy nhiên, không có "tốt hơn" vì vậy đây là một vấn đề quan điểm.
Felix Kling

@ warkentien2 Cảm ơn, điều này rất hữu ích - nhưng tôi vẫn chưa rõ quy ước ở đây là gì để trả về từ một hàm getter.
Jeremy Iglehart

1
Tôi đọc nulllà "không có giá trị thích hợp cho những gì bạn đang yêu cầu" và undefined"Tôi không thể tìm ra những gì bạn đang yêu cầu".
Marty

@ warkentien2 rằng câu hỏi, và một trong những tôi liên kết trong câu trả lời của tôi, có liên quan, nhưng cả hai dường như được hỏi những gì là sự khác biệt giữa họ và không phải là khi sử dụng một hoặc các khác như là một giá trị trả về.
ớtNUT

Câu trả lời:


37

Tôi sẽ tranh luận rằng không có cách nào tốt nhất, và ngay cả các hàm tiêu chuẩn đôi khi cũng chọn cái này hay cái kia.

Ví dụ:

  • [[Nguyên mẫu]]

    Các đối tượng thông thường có một khe bên trong [[Prototype]], nó xác định đối tượng khác mà chúng kế thừa từ đó. Tất nhiên, phải có một cách để nói rằng một đối tượng không kế thừa từ bất kỳ đối tượng nào khác. Trong trường hợp này, "không có đối tượng như vậy" được biểu diễn bằng cách sử dụng null.

  • Object.getOwnPropertyDescriptor

    Nó được mong đợi để trả về một bộ mô tả thuộc tính, nghĩa là, một đối tượng mô tả một thuộc tính (ví dụ: giá trị, khả năng ghi, khả năng liệt kê và khả năng cấu hình). Tuy nhiên, tài sản có thể không tồn tại. Trong trường hợp này, "không có tài sản đó" được đại diện bằng cách sử dụng undefined.

  • document.getElementById

    Nó được mong đợi để trả về phần tử với ID đã cho. Tuy nhiên, có thể không có phần tử nào có ID đó. Trong trường hợp này, "không có phần tử như vậy" được biểu diễn bằng cách sử dụng null.

Vì vậy, chỉ cần chọn bất cứ điều gì bạn thích hoặc nghĩ có ý nghĩa hơn cho trường hợp cụ thể của bạn.


3
sau khi đọc bài này, tôi quyết định đề xuất void 0kỹ thuật cho những người xem tương lai về câu trả lời này. Tôi cũng đã thêm một số mã để thử và làm rõ hơn quan điểm của bạn. Cảm ơn về câu trả lời của bạn!
Jeremy Iglehart

114

Không xác định thường đề cập đến một cái gì đó chưa được gán giá trị (chưa). Null đề cập đến một cái gì đó mà chắc chắn không có giá trị. Trong trường hợp đó, tôi khuyên bạn nên trả về giá trị null. Lưu ý rằng một hàm không có giá trị trả về được chỉ định mặc nhiên trả về không xác định.

Từ thông số kỹ thuật ECMAScript2015

4.3.10 giá trị không xác định

giá trị nguyên thủy được sử dụng khi một biến chưa được gán giá trị

4.3.12 giá trị null

giá trị nguyên thủy đại diện cho sự vắng mặt có chủ đích của bất kỳ giá trị đối tượng nào

http://www.ecma-international.org/ecma-262/6.0/#sec-terms-and-definitions-undefined-type

Đọc thêm:

Khi nào null hoặc undefined được sử dụng trong JavaScript?


1
Có, không xác định là giá trị được sử dụng khi một biến chưa được gán giá trị. Chính xác tại sao điều đó ngụ ý rằng bạn không nên trả về không xác định trong một hàm?
Oriol

1
@Oriol, theo suy nghĩ của tôi, vì một hàm void trả về không xác định, đó là một giá trị dành riêng cho các hàm thuộc loại đó, vì vậy khi xử lý giá trị trả về của một hàm, null cho tôi biết nó quyết định trả về null, trong khi undefined cho tôi biết điều đó hoặc quyết định trả lại không xác định, hoặc quyết định không trả lại bất cứ thứ gì, nhưng tôi chắc chắn không biết cái nào. Hơn nữa, nếu tôi đang làm vậy var x=someFunc();, tôi đang cố ý gán giá trị xa và thà rằng nó không vượt qua bất kỳ bài kiểm tra nào cho thấy nó chưa (hoặc có thể chưa) được gán giá trị. Just
imho

Đây phải là câu trả lời được chấp nhận. Đây là cách nó được dự định để được sử dụng trong thông số kỹ thuật
Zinc

1
Tôi không đọc nó theo cách đó. Tôi đọc nó là: Nếu bạn xác định một biến nhưng không khởi tạo nó, thay vào đó nó sẽ có giá trị ban đầu là không xác định. Null nên được lập trình viên sử dụng để cố ý chỉ ra rằng một biến là trống. IMHO undefined không bao giờ được người lập trình gán cho một biến, hãy để nó cho js engine sử dụng. Giá trị của thuật ngữ "đối tượng" gây hiểu lầm, vì trong JS, ngay cả các nguyên thủy cũng hoạt động giống như các đối tượng phần lớn do tự động
đóng hộp

1
Vâng, điều đó có ý nghĩa. Công bằng mà nói, tôi không ngại sử dụng cái này thay cho cái kia (mặc dù tôi đã quen hơn null) miễn là bạn gắn bó với một cái, nhưng việc có 2 giá trị để biểu thị sự vắng mặt của giá trị (bất kể "loại") luôn gây nhầm lẫn
Sergio Rosas

39

Tôi sẽ cung cấp cho bạn cách lựa chọn theo quan điểm cá nhân của tôi giữa hai điều này.

Câu hỏi đơn giản của tôi là: giá trị, được cung cấp cho một đầu vào / trạng thái / ngữ cảnh khác có thể được định nghĩa cho một cái gì đó không?

Nếu câu trả lời là có thì hãy sử dụng lệnh nullkhác undefined. Nói chung hơn, bất kỳ hàm nào trả về một đối tượng sẽ trở lại nullkhi đối tượng dự định không tồn tại. Bởi vì nó có thể tồn tại với một đầu vào / trạng thái / ngữ cảnh khác.

nullđại diện cho sự vắng mặt của giá trị cho một đầu vào / trạng thái / ngữ cảnh nhất định. Nó ngầm có nghĩa là bản thân khái niệm giá trị tồn tại trong ngữ cảnh ứng dụng của bạn nhưng có thể không có. Trong ví dụ của bạn, khái niệm về một thẻ tiếp theo tồn tại nhưng bản thân thẻ đó có thể không tồn tại. nullnên được sử dụng.

undefinedthể hiện ngầm ý nghĩa của giá trị đó trong ngữ cảnh ứng dụng của bạn. Ví dụ: nếu tôi thao tác một userđối tượng với một tập hợp các thuộc tính nhất định và tôi cố gắng truy cập thuộc tính pikatchu. Giá trị của thuộc tính này nên được đặt thành undefinedbởi vì trong ngữ cảnh của tôi, việc có một thuộc tính như vậy không có ý nghĩa gì.


1
Điều này rất đúng với tôi. Các hàm thuần túy của IMO sẽ trả về null, trong khi các hàm có tác dụng phụ sẽ trở lại undefined, khi suy nghĩ như một lập trình viên hàm.
Jake

4

undefinedkhông phải là thứ bạn nên gán cho. Bạn có thể muốn xem xét để trả lại một cái gì đó khác hơn undefined. Trong trường hợp của bạn, ngay cả khi bạn không trả lại bất cứ điều gì, kết quả sẽ là undefinedrồi. Vì vậy, tôi khuyên bạn nên đi với nullthay thế.

Hãy xem xét mẫu này,

function getSomething() {
     // .. do something
     return undefined;
}

function doSomething() {
     // .. I'm not gonna return anything.
}

var a = getSomething();
var b = doSomething();

Kết quả mẫu trên a === b, đó là undefined. Sự khác biệt là bạn tiết kiệm được 1 lần thực thi câu lệnh.


@Oriol Ý tôi là, undefinedkhông cần phải chỉ định. Tất cả các biến được khai báo không có giá trị đều đã có undefined.
choz

@choz & @Oriol - như đã đề cập trước bởi @chiliNUT "Lưu ý rằng một hàm không có giá trị trả về được chỉ định sẽ hoàn toàn trả về không xác định." - điều này đúng vì (function(){ /* code */ })()trả về null trong bảng điều khiển.
Jeremy Iglehart

@JeremyIglehart Đoạn mã đó thực sự không trả về bất kỳ thứ gì. Và khác, nó cung cấp undefinedtrên bảng điều khiển chrome và firefox của tôi.
choz

OK, tôi không hiểu ý bạn. Có, nếu bạn không trả về bất cứ thứ gì một cách rõ ràng, thì undefined sẽ được trả về một cách ngầm định. Nhưng tại sao điều đó lại quan trọng?
Oriol

1
@Oriol, tôi nghĩ điều mà @choz đang cố gắng nói (như một số người khác cũng đã đề cập đến câu hỏi này) rằng nếu tôi muốn trả lại undefinednếu thứ khác không trở lại sớm hơn - tôi không cần vì hành vi mặc định của hàm nếu bạn không trả lại bất cứ thứ gì là trả về không xác định - họ chỉ nói rằng điều này là không cần thiết. Hơn nữa ... Tôi thích những gì bạn đã nói về các hàm getter tích hợp sẵn trả về null. Hãy đăng câu trả lời của bạn cho hiệu ứng đó và tôi sẽ chấp nhận nó.
Jeremy Iglehart

3

Phụ thuộc vào những gì bạn cần làm với giá trị trả về.

typeof null trả về một đối tượng. đối tượng đó có giá trị không xác định

typeof undefined trả về undefined


Cá nhân tôi thường sử dụng null.
Dan

4
"that object has a value of undefined" Không, nó không phải và nó không phải là một đối tượng, nó là Null. typeofkhông nhất thiết phải trả về kiểu dữ liệu thực của một giá trị, nó có một bản đồ ánh xạ các kiểu dữ liệu tới các nhãn và trả về nhãn tương ứng.
Felix Kling

Đừng tin tưởng typeof, mặc dù tên của nó, nó không cho biết loại giá trị.
Oriol

2

Đây là một ví dụ có undefinedý nghĩa hơn null:

Tôi sử dụng một hàm wrapper để JSON.parsechuyển đổi ngoại lệ của nó thành undefined:

// parses s as JSON if possible and returns undefined otherwise
// return undefined iff s is not a string or not parseable as JSON; undefined is not a valid JSON value https://stackoverflow.com/a/14946821/524504
function JSON_parse_or_undefined(s) {
    if ("string" !== typeof s) return undefined

    try {
        const p = JSON.parse(s)
        return p
    } catch (x){}

    return undefined
}

Lưu ý rằng điều đó nullhợp lệ trong JSON trong khi undefinedthì không.


Tôi thấy bạn đang làm gì ở đó - và tôi không thể nói bạn sai - bởi vì theo một nghĩa nào đó, tôi nghĩ bạn có thể làm điều này ở đây và nó sẽ ổn thôi. Tôi có một mẫu khác mà tôi sử dụng để thực hiện thao tác này mà tôi thích hơn vì tôi thực hiện bước "xác thực" sau đó. Tôi cảm thấy như điều này đang nhận được xác thực kết hợp với việc trả về giá trị. Dưới đây là những gì tôi làm: let getStringOrJSON = value => { try { value = JSON.parse(value); } catch(e) { return value; } return value; };. Bây giờ, tôi chắc chắn rằng hai lượt trả về có thể được xử lý khác nhau và có thể không thắng trong cuộc thi chơi gôn JS. Nó hoạt động.
Jeremy Iglehart,

1

Câu trả lời đầu tiên là đúng. Chúng có ý nghĩa khác nhau về mặt lý thuyết. Tuy nhiên, không phải lúc nào cũng rõ ràng nên chọn cái nào.

Tôi có xu hướng sử dụng null trong quá trình phát triển của mình mặc dù tôi nghĩ đó là điều hoàn toàn chủ quan.

Tôi sử dụng nó chủ yếu vì:

  1. biến undefined có thể bị ghi đè trong các trình duyệt cũ nên việc trả lại nó phức tạp hơn một chút. Vấn đề tương tự này buộc bạn phải sử dụng typeof var === 'undefined'khi nhận kết quả hàm. liên kết

  2. Các ngôn ngữ khác có xu hướng sử dụng null rộng rãi, nhiều ngôn ngữ thậm chí không có undefined (php chẳng hạn). Điều đó mang lại cho tôi sự nhất quán khi nhanh chóng hoán đổi giữa các ngôn ngữ.


1

Tôi nghĩ rằng nó là rất đáng tranh luận để sử dụng. Tôi thích mã càng chính xác về mặt ngữ nghĩa càng tốt, vì vậy tôi nghĩ undefinedlà phù hợp trong trường hợp này.

Tôi nghĩ về các nullphép gán có nghĩa là "một biến được đặt thành không". Điều này trái ngược với undefinednghĩa là "thứ này hoàn toàn không có"

Như một câu trả lời trước đây đã chỉ ra, việc quay lại undefinedcó vấn đề và việc đó có làm phiền bạn hay không hoàn toàn phụ thuộc vào bạn. Nó sẽ không làm phiền tôi.


2
Nhưng document.getElementById('iDoNotExist')trả lại null, mặc dù nghĩa gần với "thứ này không có ở đó cả". Nếu các phương pháp tiêu chuẩn làm được điều đó, tại sao không OP?
Oriol

@Oriol Tôi thực sự thích lý luận của bạn nhất. Vui lòng đăng câu trả lời cho hiệu ứng này và tôi sẽ chấp nhận nó. (Tôi thậm chí có thể thêm một vài chỉnh sửa nếu cần)
Jeremy Iglehart

Yah @Oriol, đây là lý do tại sao tôi thực sự thích các cuộc tranh luận, ngay cả trên các trang Hỏi / Đáp. Thực sự tốt để có được các ví dụ truy cập. Và bạn đã cung cấp một cái tốt.
Ryan Laboucane

1

Tôi lập luận rằng trong trường hợp này, nullnên được trả lại.

Nếu bạn xem xét câu hỏi từ quan điểm khoa học máy tính lý thuyết thì undefined được sử dụng để biểu thị tính không kết thúc / không tính toán được (tức là trình giữ chỗ cho một điểm không xác định xcủa một hàm từng phần f thường được viết f(x) = ⊥).

getNextCardtuy nhiên dường như có thể tính toán thẻ tiếp theo (nếu nó tồn tại) và cũng có thể tính toán nếu không có thẻ tiếp theo. Nói cách khác, hàm là tổng vì nó kết thúc đối với mọi đầu vào.

Điều đó đang được nói, một giá trị đặc biệt báo hiệu kết thúc mà không có kết quả có ý nghĩa (tức là "không có thẻ nào tôi có thể trả lại cho đầu vào này") là bắt buộc và điều này đối với tôi thì nullkhông undefined.


LƯU Ý:

Bạn có thể thấy một số hỗ trợ cho đối số này trong một số ngôn ngữ được đánh máy khác cũng như khi kết thúc mà không có kết quả có ý nghĩa được thể hiện bằng cách sử dụng một loại tùy chọn (đôi khi cũng được gọi là kiểu nullable ). Một ví dụ cho điều này là Có thể trong Haskell .

Mặt khác, tất nhiên chúng ta không biết undefinedJavaScript thực sự nghĩa là gì. Vì vậy, tương tự với không xác định là một chút mệt mỏi. Hơn nữa, vì chúng ta luôn muốn làm việc với các hàm tổng, điều này tương đương với câu nói "không bao giờ trả về undefinedtừ một hàm". Điều này có vẻ hơi nghiêm ngặt, vì nó sẽ giới hạn việc sử dụng các undefinedthuộc tính / biến chưa được thiết lập.

Cuối cùng, sở thích cá nhân của tôi là không bao giờ quay trở lại undefinednơi tôi có thể quay lại nullvà tôi cũng sẽ tranh luận rằng đây là quy ước mã hóa tốt hơn (vì trong số những thứ khác x !== nullthì ngắn hơn typeof x !== 'undefined').


-1

Ý kiến ​​cá nhân của tôi theo kinh nghiệm của tôi là đừng sử dụng undefined và null nếu bạn không muốn code của mình bị crash. Ít nhất thì tôi sẽ tránh nó một cách cá nhân. Có rất nhiều hàm trong Javascript trả về không xác định và chúng ta phải sử dụng nó. Nhưng khi bạn thiết kế mã của bạn không sử dụng nó. Điều quan trọng là luôn luôn trả lại một cái gì đó "false"ít nhất. Nếu bạn có một mảng chẳng hạn và bạn ánh xạ lên nó. Nó không phải là tốt để trở lại [undefined, undefined.....]hoặc chỉ undefined. Sẽ tốt hơn nếu bạn giữ nguyên kiểu của mảng ban đầu. Thí dụ:

 const mapper:Map <string[],boolean[]>  
['i', 'dont', 'use', 'null or undefined'] -> [false, true, false, true, false]
or ['', dont, '', '', use] 
or al the stuff above and then filter(v => v)
that will keep all undefined and null out

Đó là ý tưởng. Tôi cố gắng mọi lúc để tránh nó. Vì một nullhoặc undefinedcó thể dễ dàng làm hỏng mã của bạn

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.