12 行代码跑通 freeCodeCamp 的 Profile Lookup:对象数组查找与括号属性访问
【免费下载链接】TVBoxOSCTVBoxOSC - 一个基于第三方项目的代码库,用于电视盒子的控制和管理。项目地址: https://gitcode.com/GitHub_Trending/tv/TVBoxOSC
在 freeCodeCamp 的 Profile Lookup 挑战里,你要按姓名在对象数组里查联系人,并返回他的某个属性。可如果凭直觉写,lookUpProfile("Akira", "likes")完全可能返回undefined。本文用这道对象数组查找题,讲清括号属性访问的用法、两种缺失语义的处理,12 行代码全部讲透——适合正在刷 JS 基础练习、又被这类函数题卡住的你。
先查人、再查属性:把题面翻译成判定表
函数签名是固定的:lookUpProfile(name, prop),name是名字字符串,prop是属性名字符串。被查询的数据是contacts对象数组,每个元素代表一个人:
const contacts = [ { firstName: "Akira", lastName: "Laine", number: "0543236543", likes: ["Pizza", "Coding"] }, { firstName: "Kristian", lastName: "Vos", number: "unknown", likes: ["JavaScript", "Gaming"] }, // ... 其余两个略 ]; function lookUpProfile(name, prop) { // Only change code below this line }注意字段是异构的:number是字符串,likes是数组,各对象拥有的属性集合也不完全一样。判定逻辑由此拆成三条分支:
- 成功分支:某个联系人的
firstName与name相等,且prop确实是这个对象的属性 → 原样返回该属性的值,字符串就返回字符串,数组就返回数组。 - 失败分支 A(缺人):整个数组里没有任何
firstName匹配name→ 返回"No such contact",此时prop是否合法都不重要。 - 失败分支 B(缺属性):人找到了,但
prop不在那个对象上 → 返回"No such property"。
关键在后半句:两种失败语义不同,优先级固定。先判人,人查不到就直接报"缺人";人命中之后才轮到判属性。顺序一颠倒,lookUpProfile("Bob", "potato")就会被判成"属性不存在",而官方预期是"人不存在"。
两种写法一次讲透:官方短路与显式检查
官方版:for...in 加 ||
freeCodeCamp 的参考答案用for...in遍历下标,再用一个||兜底:
function lookUpProfile(name, prop) { for (let i in contacts) { // i 依次取 "0"、"1"、"2"、"3" if (contacts[i].firstName === name) { // 括号访问读取 prop 指向的属性,取不到就用 || 兜底 return contacts[i][prop] || "No such property"; } } // 整轮遍历没命中,才说明这个人不在数组里 return "No such contact"; }为什么return "No such contact"要放在循环外面?因为必须把整个数组走完、firstName一个都没对上,才能下结论"人不在通讯录里";若第一个对象没匹配就报缺人,等于把后面的数据全部误判为不存在。而一旦命中就立刻return,"先查人、后查属性"的顺序天然被保住。这里用到的括号属性访问,就是obj[key]里key为变量时的读法——prop是运行时传进来的键名,只有括号语法才能解释它。
⚠️边界提示:contacts[i][prop]在属性不存在时读到undefined,||顺势换成提示语。可当合法值本身就是假值——比如age: 0、flag: false、空字符串——||会把正常返回值一并吞掉,误报 "No such property"。官方测试数据里恰好都是真值,所以能过,但这个隐患是真实存在的。
更稳的版本:for...of 加 hasOwnProperty
function lookUpProfile(name, prop) { for (const contact of contacts) { if (contact.firstName === name) { // 只问"属性在不在",不问"值是不是真值" if (Object.prototype.hasOwnProperty.call(contact, prop)) { return contact[prop]; // 0、false、空串都原样返回 } return "No such property"; } } return "No such contact"; }与官方版相比只有两处差异:直接遍历对象本体而不是下标,以及把||捷径换成一次显式的hasOwnProperty.call检查。hasOwnProperty(判断对象是否拥有某个自有属性)只关心"在不在",不关心"值真假",于是age: 0这类假值会被如实返回 0,而官方版会把它误报成"缺属性"。两者都能通过全部官方断言,但后一种在语义上更诚实。
四个高频错误:错误代码改正确代码
- 点语法取属性:
contact.prop→contact[prop]。点语法读的是字面键"prop",永远是undefined;变量只能经括号解释为键名。 - 判空顺序写反:先查
prop是否合法再找人 → 人命中之后才查prop。否则lookUpProfile("Bob", "potato")会错报 "No such property"。 - 对整数组做统一 prop 校验:拿
prop去挨个校验所有联系人 → 只对命中的那个对象校验。字段各不一致,有效性只能以实际匹配到的对象为准。 - 把 likes 拼成字符串:
contact.likes.join(", ")→contact.likes。断言校验返回值是数组,join 一转成字符串就挂了。
在 freeCodeCamp 仓库里验证它 🔍
挑战文件curriculum/challenges/english/blocks/basic-javascript/5688e62ea601b2482ff8422b.md的 front-matter 记录了challengeType: 1(浏览器控制台函数题)与dashedName: profile-lookup。其中的--hints--段落就是断言脚本:在线编辑器运行时,它会拿你的补全函数逐条执行 assert;--seed-contents--段落则是你在编辑器里看到的初始代码,只有注释标出的区域开放编辑。
回到自己的控制台验证
- 把
||换成hasOwnProperty.call,再跑一遍全部六条断言,确认行为一致。 - 手工给 contacts 加一个
number: 0的联系人,分别调用两种写法,看一个返回 "No such property"、另一个返回 0。 - 用
contacts.find(c => c.firstName === name)加可选链重写循环,体验函数式风格。
现在就把这道题做掉,然后到空文件里手写本文的三种版本——当你能说清每个版本会吞掉哪些假值时,这道题才算真正属于你。
【免费下载链接】TVBoxOSCTVBoxOSC - 一个基于第三方项目的代码库,用于电视盒子的控制和管理。项目地址: https://gitcode.com/GitHub_Trending/tv/TVBoxOSC
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考