null 和 undefined 都表示“无值”的概念,但它们的含义和使用场景有所不同。正确判断它们对于避免 bug 和编写健壮的代码非常重要。
一、null 与 undefined 的区别
1. 含义不同
undefined:变量已声明但未赋值,函数无返回值,对象不存在的属性
null:表示“空值”的对象引用,通常由开发者显式设置
2. 类型不同
typeof undefined; // "undefined"
typeof null; // "object" (历史遗留问题)
二、判断方法对比
1. 严格相等判断(推荐)
// 判断 undefined
let value;
value === undefined; // true
// 判断 null
let obj = null;
obj === null; // true
// 判断 null 或 undefined
value == null; // true (因为 undefined == null 返回 true)
value === null || value === undefined; // 更明确的方式
2. 松散相等的问题
null == undefined; // true
null == 0; // false
undefined == 0; // false
三、实用判断函数
1. 基本判断函数
// 判断是否为 null
function isNull(value) {
return value === null;
}
// 判断是否为 undefined
function isUndefined(value) {
return value === undefined;
}
// 判断是否为 null 或 undefined
function isNullOrUndefined(value) {
return value == null; // 或 value === null || value === undefined
}
2. 安全访问的辅助函数
// 安全的属性访问
function safeGet(obj, path, defaultValue = undefined) {
const keys = path.split('.');
let result = obj;
for (const key of keys) {
if (result == null) {
return defaultValue;
}
result = result[key];
}
return result === undefined ? defaultValue : result;
}
// 示例
const user = { profile: { name: 'John' } };
safeGet(user, 'profile.name'); // 'John'
safeGet(user, 'profile.age', 25); // 25
safeGet(user, 'address.city', 'Unknown'); // 'Unknown'
四、ES6+ 的新特性
1. 空值合并运算符 ??
const value1 = undefined ?? 'default'; // 'default'
const value2 = null ?? 'default'; // 'default'
const value3 = 0 ?? 'default'; // 0 (与 || 不同)
2. 可选链操作符 ?.
const user = { profile: { name: 'John' } };
// 传统方式
const name = user && user.profile && user.profile.name;
// 可选链
const name = user?.profile?.name; // 'John'
const age = user?.profile?.age; // undefined
// 结合空值合并
const safeAge = user?.profile?.age ?? 0; // 0
3. 默认参数值
function greet(name = 'Guest') {
console.log(`Hello, ${name}`);
}
greet(); // "Hello, Guest" (undefined 时使用默认值)
greet(null); // "Hello, null" (null 不会触发默认值)
五、实际应用场景
1. API 响应处理
async function fetchUserData() {
try {
const response = await fetch('/api/user');
const data = await response.json();
// 处理可能为 null 或 undefined 的数据
return {
name: data?.name ?? 'Anonymous',
age: data?.age ?? 0,
email: data?.email ?? 'N/A'
};
} catch (error) {
console.error('Error:', error);
return null;
}
}
2. 表单验证
function validateForm(data) {
const errors = {};
// 检查必填字段
if (data.username == null || data.username.trim() === '') {
errors.username = '用户名不能为空';
}
// 使用 ?? 提供默认值
const age = data.age ?? 0;
if (age < 18) {
errors.age = '年龄必须满18岁';
}
return Object.keys(errors).length === 0 ? null : errors;
}
3. 配置对象合并
function mergeConfig(defaultConfig, userConfig) {
return {
timeout: userConfig?.timeout ?? defaultConfig.timeout,
retries: userConfig?.retries ?? defaultConfig.retries,
baseUrl: userConfig?.baseUrl ?? defaultConfig.baseUrl
};
}
六、最佳实践
优先使用 === 和 !== 进行精确比较
使用 == null 同时检查
null 和
undefined
善用 ES6+ 特性,如可选链和空值合并
在函数参数中明确处理 null 和 undefined
API 设计要一致,避免混用 null 和 undefined
总结
正确判断 null 和 undefined 的关键在于理解它们的区别并选择合适的判断方法。现代 JavaScript 提供了更优雅的方式来处理这些“空值”情况,合理使用这些特性可以让代码更加简洁和健壮。