const user = { name: 'John', age: 30 };我们想在访问name键之前检查它是否存在:
if (user.name) { console.log(user.name); }这个方法表面上看没问题,但如果name键存在但值是undefined会怎样呢?
const user = { name: undefined }; if (user.name) { // 这段代码不会执行! }直接访问一个不存在的键会返回undefined,但是访问值为undefined的键也是返回undefined。所以我们不能依赖直接键访问来检查键是否存在。
if (typeof user.name !== 'undefined') { console.log(user.name); }typeof会对不存在的键返回"undefined",对存在的键返回其它类型,如"string"。然而,这种方法有几个缺点:
4.容易拼写错误'undefined'
if ('name' in user) { console.log(user.name); }这种方法比typeof更简洁:
if (user.hasOwnProperty('name')) { console.log(user.name); }这种方法只会返回对象自身拥有的键,而不会检查继承的属性:
const user = { name: 'John' }; let key = 'name'; function directAccess() { return user[key] !== undefined; } function inOperator() { return key in user; } function hasOwnProperty() { return user.hasOwnProperty(key); } function typeofCheck() { return typeof user[key] !== 'undefined'; } function objectKeysCheck() { return Object.keys(user).includes(key); } // 堆代码 duidaima.com // 运行每个函数100万次 let start = performance.now(); for (let i = 0; i < 1000000; i++) { directAccess(); } console.log(`directAccess took ${performance.now() - start} ms`); start = performance.now(); for (let i = 0; i < 1000000; i++) { inOperator(); } console.log(`inOperator took ${performance.now() - start} ms`); start = performance.now(); for (let i = 0; i < 1000000; i++) { hasOwnProperty(); } console.log(`hasOwnProperty took ${performance.now() - start} ms`); start = performance.now(); for (let i = 0; i < 1000000; i++) { typeofCheck(); } console.log(`typeofCheck took ${performance.now() - start} ms`); start = performance.now(); for (let i = 0; i < 1000000; i++) { objectKeysCheck(); } console.log(`objectKeysCheck took ${performance.now() - start} ms`);结果如下( 测试机器:apple m1 ,内存16G):
directAccess耗时 1.59 毫秒 inOperator 耗时 0.97 毫秒(注:inOperator 和 typeofCheck 有时会比较接近) hasOwnProperty耗时 4.74 毫秒 typeofCheck耗时 1.16 毫秒 Object.keys()耗时 8.48 毫秒如上所示,inOperator 运算显著快于其他方法。
5.Object.keys()方法直观,但速度最慢