Tuổi cũ chủ đề, nhưng có những cách mới để chạy một tương đương isset()
.
ESNext (Giai đoạn 4 tháng 12 năm 2019)
Hai cú pháp mới cho phép chúng tôi đơn giản hóa rất nhiều việc sử dụng isset()
chức năng:
Xin vui lòng đọc các tài liệu và quan tâm đến khả năng tương thích trình duyệt.
Trả lời trước
Xem bên dưới để giải thích. Lưu ý tôi sử dụng cú pháp StandardJS
Cách sử dụng ví dụ
// IMPORTANT pass a function to our isset() that returns the value we're
// trying to test(ES6 arrow function)
isset(() => some) // false
// Defining objects
let some = { nested: { value: 'hello' } }
// More tests that never throw an error
isset(() => some) // true
isset(() => some.nested) // true
isset(() => some.nested.value) // true
isset(() => some.nested.deeper.value) // false
// Less compact but still viable except when trying to use `this` context
isset(function () { return some.nested.deeper.value }) // false
Chức năng trả lời
/**
* Checks to see if a value is set.
*
* @param {Function} accessor Function that returns our value
*/
function isset (accessor) {
try {
// Note we're seeing if the returned value of our function is not
// undefined
return typeof accessor() !== 'undefined'
} catch (e) {
// And we're able to catch the Error it would normally throw for
// referencing a property of undefined
return false
}
}
Giải trình
PHP
Lưu ý rằng trong PHP bạn có thể tham chiếu bất kỳ biến nào ở bất kỳ độ sâu nào - thậm chí cố gắng truy cập vào một mảng không phải là một mảng sẽ trả về một đơn giản true
hoặc false
:
// Referencing an undeclared variable
isset($some); // false
$some = 'hello';
// Declared but has no depth(not an array)
isset($some); // true
isset($some['nested']); // false
$some = ['nested' => 'hello'];
// Declared as an array but not with the depth we're testing for
isset($some['nested']); // true
isset($some['nested']['deeper']); // false
Mã não
Trong JavaScript, chúng tôi không có quyền tự do đó, chúng tôi sẽ luôn gặp lỗi nếu chúng tôi làm điều tương tự vì JS ngay lập tức cố gắng truy cập giá trị deeper
trước khi chúng tôi có thể bọc nó trong isset()
chức năng của mình để ...
// Common pitfall answer(ES6 arrow function)
const isset = (ref) => typeof ref !== 'undefined'
// Same as above
function isset (ref) { return typeof ref !== 'undefined' }
// Referencing an undeclared variable will throw an error, so no luck here
isset(some) // Error: some is not defined
// Defining a simple object with no properties - so we aren't defining
// the property `nested`
let some = {}
// Simple checking if we have a declared variable
isset(some) // true
// Now trying to see if we have a top level property, still valid
isset(some.nested) // false
// But here is where things fall apart: trying to access a deep property
// of a complex object; it will throw an error
isset(some.nested.deeper) // Error: Cannot read property 'deeper' of undefined
// ^^^^^^ undefined
Nhiều lựa chọn thay thế thất bại:
// Any way we attempt to access the `deeper` property of `nested` will
// throw an error
some.nested.deeper.hasOwnProperty('value') // Error
// ^^^^^^ undefined
Object.hasOwnProperty('value', some.nested.deeper) // Error
// ^^^^^^ undefined
// Same goes for typeof
typeof some.nested.deeper !== 'undefined' // Error
// ^^^^^^ undefined
Và một số lựa chọn thay thế có thể nhận được dự phòng nhanh chóng:
// Wrap everything in try...catch
try { isset(some.nested.deeper) } catch (e) {}
try { typeof some.nested.deeper !== 'undefined' } catch (e) {}
// Or by chaining all of the isset which can get long
isset(some) && isset(some.nested) && isset(some.nested.deeper) // false
// ^^^^^^ returns false so the next isset() is never run
Phần kết luận
Tất cả các câu trả lời khác - mặc dù hầu hết đều khả thi ...
- Giả sử bạn chỉ kiểm tra xem biến đó không được xác định, điều này tốt cho một số trường hợp sử dụng nhưng vẫn có thể gây ra Lỗi
- Giả sử bạn chỉ đang cố gắng truy cập vào một thuộc tính cấp cao nhất, một lần nữa sẽ tốt cho một số trường hợp sử dụng
- Buộc bạn sử dụng một cách tiếp cận ít lý tưởng hơn so với PHP,
isset()
vdisset(some, 'nested.deeper.value')
- Sử dụng
eval()
mà hoạt động nhưng cá nhân tôi tránh
Tôi nghĩ rằng tôi bao gồm rất nhiều nó. Có một số điểm tôi đưa ra trong câu trả lời của mình mà tôi không đề cập đến vì chúng - mặc dù có liên quan - không phải là một phần của câu hỏi. Tuy nhiên, nếu cần, tôi có thể cập nhật câu trả lời của mình bằng các liên kết đến một số khía cạnh kỹ thuật hơn dựa trên nhu cầu.
Tôi đã dành nhiều thời gian cho việc này vì vậy hy vọng nó sẽ giúp được mọi người.
Cảm ơn bạn đã đọc!