Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >如何高效检查JavaScript对象中的键是否存在

如何高效检查JavaScript对象中的键是否存在

作者头像
前端达人
发布于 2024-07-10 10:58:09
发布于 2024-07-10 10:58:09
2.4K00
代码可运行
举报
文章被收录于专栏:前端达人前端达人
运行总次数:0
代码可运行

在日常开发中,作为一个JavaScript开发者,我们经常需要检查对象中某个键是否存在。这看似简单,但其实有多种方法可供选择,每种方法都有其独特之处。本文将介绍几种检查JavaScript对象键的方法,并比较它们的性能。

问题背景

假设我们有一个简单的对象:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const user = {
  name: 'John',
  age: 30 
};

我们想在访问name键之前检查它是否存在:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
if (user.name) {
  console.log(user.name); 
}

这个方法表面上看没问题,但如果name键存在但值是undefined会怎样呢?

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const user = {
  name: undefined
};

if (user.name) {
  // 这段代码不会执行!
}

直接访问一个不存在的键会返回undefined,但是访问值为undefined的键也是返回undefined。所以我们不能依赖直接键访问来检查键是否存在。

使用typeof

一种常见的方法是使用typeof来检查类型:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
if (typeof user.name !== 'undefined') {
  console.log(user.name);
}

typeof会对不存在的键返回"undefined",对存在的键返回其它类型,如"string"。然而,这种方法有几个缺点:

  • 需要额外的操作(typeof)而不是直接比较
  • 比较冗长且需要否定检查(!==
  • 可读性不如其他方法
  • 容易拼写错误'undefined'

使用in操作符

in操作符允许我们检查键是否存在于对象中:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
if ('name' in user) {
  console.log(user.name); 
}

这种方法比typeof更简洁:

  • 简单且可读
  • 内置语言特性,专为此设计
  • 对所有值都有效,包括undefined

但是,in操作符也会检查对象的原型链。因此它对原型链上存在的键也会返回true

使用hasOwnProperty

要仅检查对象自身的键,可以使用hasOwnProperty

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
if (user.hasOwnProperty('name')) {
  console.log(user.name);
}

这种方法只会返回对象自身拥有的键,而不会检查继承的属性:

  • 只检查自身键,不包括继承的
  • 方法名清晰,容易理解

缺点是hasOwnProperty需要方法调用,在性能关键的代码中可能会有影响。

性能比较

哪种方法最快呢?以下是直接键访问、inhasOwnPropertytypeof的简单性能比较:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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);
}

// 运行每个函数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 运算显著快于其他方法。

总结
  • 直接键访问较快且易读但无法处理undefined
  • in操作符最快但能处理所有值,包括undefined
  • hasOwnProperty较慢但只检查对象自身的键
  • typeof速度较快但需要冗长的否定检查
  • Object.keys()方法直观,但速度最慢

在大多数情况下,in操作符在可读性和性能之间提供了最佳平衡。只有在需要排除继承键时才使用hasOwnProperty

理解这些不同方法的细微差别是检查JavaScript键的关键。根据具体需求选择合适的工具,除非性能至关重要,否则应优先考虑可读性。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-07-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 前端达人 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
JavaScript·JavaScript 秘密花园
JavaScript 秘密花园由两位 Stack Overflow 用户伊沃·韦特泽尔(写作)和张易江(设计)完成,由三生石上翻译完成,内容短小精炼。这次温故知新,做一番总结。
数媒派
2022/12/01
7330
有个开发者总结这 15 优雅的 JavaScript 个技巧
JavaScript 有很多很酷的特性,大多数初学者和中级开发人员都不知道。今天分享一些,我经常在项目中使用一些技巧。
前端小智@大迁世界
2022/06/15
7630
有个开发者总结这 15 优雅的 JavaScript 个技巧
React 中,用到的几种浅比较方式及其比较成本科普
开发中的绝大多数时候,我们并不需要关注 React 项目的性能问题。虽然我们在前面几个章节中,也花了几篇文章来分析如何优化 React 的性能体验,但是这些知识点在开发过程中能用到的机会其实比较少。面试的时候用得比较多。
用户6901603
2024/01/17
4110
React 中,用到的几种浅比较方式及其比较成本科普
javascript 中的解构技巧
在实际项目开发中,检测一个对象中是否包含某个键值来避免引用不存在的元素,来避免undefined的引用错误,而因为js又是单线程这一特点,一旦报错将影响后续逻辑执行,所以进行引入的键和值是否存在显得尤为重要,以下是我整理的几种判断和解构方法
iwhao
2024/07/03
1920
大型前端如何分析用户行为和追踪函数调用链
在很多时候我们项目越来越大的时候,我们希望去监听局部某些类方法的性能,这个时候我们既不想影响源代码的功能,但又想借助某些方案去窥探类方法内部的运行效能,此时我们就可以考虑使用装饰器对类方法性能进行监听。装饰器相信大家都不陌生了,虽然在 Javasript 里面它仍处于提议阶段,但是我们已经可以 TypeScript 里面运用这个特性,也可以借助 babel 的语法转换在 Javasript 里面使用。
wscats
2020/06/18
2K0
大型前端如何分析用户行为和追踪函数调用链
70个JavaScript面试问题
它们是属于虚值,可以使用Boolean(value)或!!value将其转换为布尔值时,值为false。
前端迷
2020/02/19
1.6K0
70个JavaScript面试问题
JavaScript基础③
这里要特别说明一下localStorage的使用也是遵循同源策略的,所以不同的网站直接是不能共用相同的localStorage
ymktchic
2022/01/18
6060
JavaScript基础③
【JS】676- 1.1w字 | 初中级前端 JavaScript 自测清单 - 2
前言 在《初中级前端 JavaScript 自测清单 - 1》部分中,和大家简单过了一遍 JavaScript 的一些基础知识,没看过的朋友可以回顾一下? 本系列文章是我在我们团队内部的“「现代 Ja
pingan8787
2020/08/11
1.2K0
【JS】676- 1.1w字 | 初中级前端 JavaScript 自测清单 - 2
JavaScript中的这些骚操作,你都知道吗?
写这篇文章的缘由是上周在公司前端团队的code review时,看了一个实习小哥哥的代码后,感觉一些刚入行不久的同学,对于真实项目中的一些js处理不是很熟练,缺乏一些技巧。
前端森林
2020/05/26
5960
使用JavaScript的一些小技巧
https://www.w3cplus.com/javascript/javascript-tips.html
@超人
2021/02/26
1.7K0
使用JavaScript的一些小技巧
JavaScript原型与继承
对于使用过基于类的语言 (如 Java 或 C++) 的开发人员来说,JavaScript 有点令人困惑,因为它是动态的,并且本身不提供一个 class 实现。(在 ES2015/ES6 中引入了 class 关键字,但那只是语法糖,JavaScript 仍然是基于原型的)。
用户1428723
2020/08/06
6030
送你43道JavaScript面试题
这两天的GitHub Trending repositories被一个名叫 javascript-questions的项目霸榜了,项目中记录了一些JavaScript题目。
ConardLi
2019/06/19
1.7K0
送你43道JavaScript面试题
一篇文章带你了解JavaScript中的语法,数据类型,流程控制语句以及函数
JavaScript有多重要啊,才能让我说说一下,其中的语法,操作符,数据类型,内置功能等。
达达前端
2019/12/26
6060
一篇文章带你了解JavaScript中的语法,数据类型,流程控制语句以及函数
看完这几道 JavaScript 面试题,让你与考官对答如流(下)
async/await是 JS 中编写异步或非阻塞代码的新方法。它建立在Promises之上,让异步代码的可读性和简洁度都更高。
前端小智@大迁世界
2022/06/15
2.1K0
JavaScript 高级程序设计(第 4 版)- 对象、类与面向对象编程
通过字面量来重写原型时,Person.prototype被设置为等于一个通过对象字面量创建的新对象,此时Person.prototype的constructor属性就不指向Person了
Cellinlab
2023/05/17
6940
JavaScript 高级程序设计(第 4 版)- 对象、类与面向对象编程
【JS】307- 复习 Object.assign 原理及其实现
上篇文章介绍了赋值、浅拷贝和深拷贝,其中介绍了很多赋值和浅拷贝的相关知识以及两者区别,限于篇幅只介绍了一种常用深拷贝方案。
pingan8787
2019/08/06
1.3K0
javascript模式 读书笔记一
模式是指一个通用问题的解决方案。 模式分三种 设计模式 编码模式:javascript特有的
lilugirl
2019/05/26
1.1K0
对象数据的读取,看这一篇就够了!Object.keys()、Object.values()和Object.entries()用法详解;如何获取对象原型链上的属性
返回一个包含对象自身可枚举属性的键数组。这个方法只考虑对象自身的属性,不考虑原型链上的属性。
watermelo37
2025/01/22
4200
对象数据的读取,看这一篇就够了!Object.keys()、Object.values()和Object.entries()用法详解;如何获取对象原型链上的属性
JavaScript 进阶问题列表[每日前端夜话0x95]
来源:https://github.com/lydiahallie/javascript-questions
疯狂的技术宅
2019/07/17
1.5K0
JavaScript 进阶问题列表[每日前端夜话0x95]
大话 JavaScript(Speaking JavaScript):第十六章到第二十章
您在不运行程序的情况下检查程序的存在。给定以下代码,我们可以得出静态断言,即函数“g”嵌套在函数“f”内部:
ApacheCN_飞龙
2024/01/12
6280
大话 JavaScript(Speaking JavaScript):第十六章到第二十章
推荐阅读
相关推荐
JavaScript·JavaScript 秘密花园
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验