task:
我們有一個對象數組,里面存儲着通訊錄。
函數 lookUp
有兩個預定義參數:firstName
值和prop
屬性 。
函數將會檢查通訊錄是否存在一個聯系人的firstName
屬性等於firstName
值,還會檢查對應聯系人是否存在 prop
屬性。
如果它們都存在,函數返回prop
屬性對應的值。
如果firstName
值不存在,返回 "No such contact"
。
如果prop
屬性不存在,返回 "No such property"
。
var contacts = [ { "firstName": "Akira", "lastName": "Laine", "number": "0543236543", "likes": ["Pizza", "Coding", "Brownie Points"] }, { "firstName": "Harry", "lastName": "Potter", "number": "0994372684", "likes": ["Hogwarts", "Magic", "Hagrid"] }, { "firstName": "Sherlock", "lastName": "Holmes", "number": "0487345643", "likes": ["Intriguing Cases", "Violin"] }, { "firstName": "Kristian", "lastName": "Vos", "number": "unknown", "likes": ["Javascript", "Gaming", "Foxes"] } ];
拿到題目后首先用了for循環,下面是代碼。
function lookup(firstName,prop) { for (var i = 0; i < contacts.length; i++) { if (contacts[i].firstName == firstName) { if (contacts[i].hasOwnProperty(prop)) { return contacts[i].prop; } else { return 'no such property'; } }else{ return 'no such contact'; } } }
提交代碼后並沒有通過(逃
之后拿去打斷點調試發現存在兩個問題 請往下看
問題1: contacts[i].prop 總是返回undefined
有兩個可能導致這個問題。一是上面的if條件寫錯。二是contacts[i].prop表達式不合法。
由於if條件可以正常返回true or false 所以排除這個原因。然后我改用contacts[i][prop]顯示了正確結果。經過自己的測試對比發現 點操作 並不能用於通過變量獲取屬性。舉個栗子。
var arr = [ { "name": 'qi', "hobby":['a','b','c'] }, { "name": 'zz', "hobby": ['x', 'y', 'z'] } ]; var str = 'hobby'; if (arr[0].hasOwnProperty('hobby')) { alert(arr[0][str]); //a,b,c alert(arr[0].str); //undefined }
點操作取不到值別怕,我們可以使用中括號操作符。當通過變量名訪問屬性的時候,不需要給變量名包裹引號。因為實際上我們使用的是變量的值,而不是變量的名稱。但用普通方式獲取屬性的時候需要加引號:arr[0]['hobby']。另外屬性名中有空格的情況下只能用中括號操作符獲取屬性值:arr[0]['pop dog'].
總結:1. 通過變量獲取屬性值時不能用點操作符必須使用中括號。2. 屬性名中有空格或連字符等特殊符號時需要中括號。
問題2: for循環執行一次整個函數就返回
還未遍歷到想要查找的聯系人就已經退出了。必須該返回的時候返回,不該返回的時候繼續往下執行。如果要用for循環也只能在循環里設置一個 return 出口。
正確實現:先找出符合 firstName 的一個組,后判斷里面是否有prop屬性。
function lookup(firstName,prop){ var result=contacts.filter(function(item){ return item.firstName == firstName; }); if(result.length){ //符合的結果組只有一個 return result[0][prop]?result[0][prop]:'no such property' } return 'no such contact'; }