2016-08-03 2 views
0

Я хочу, чтобы иметь возможность циклически перемещаться по объекту JSON и возвращать значение, основанное на том, что я ищу. Скажем, что объект содержит людей, у каждого человека есть имя и почтовый индекс. Я хочу функцию, которая вернет zipcode, когда я передам ему имя.Необходимо передать данные в JavaScript для каждой функции

Следующий код дает мне «неопределенную» ошибку, поэтому она должна быть чем-то связана с областью видимости.

var myArray=[ 
    { 
     "name":"Joe", 
     "zip":90210 
    }, 
    { 
     "name":"Bill", 
     "zip":94109 
    } 
]; 

function findIt(myArray,target) { 
    myArray.forEach(function (person) { 
     if (person.name === target) { 
      return person.zip; 
     } 
    }); 
} 
var zip=findIt(myArray,"Joe"); 
+0

Это не JSON. Нет такой вещи, как «объект JSON». JSON всегда является строкой. Всегда. У вас есть массив объектов. – naomik

+2

Функция findIt не возвращает ничего, поэтому не определена в результате –

+2

Используйте 'filter' (или' find', если вы используете ES6) вместо 'forEach'. – str

ответ

2

Вы возвращаетесь почтовый индекс от анонимного внутренней функции, а не из findIt функции.

Для решения этой проблемы вы можете сохранить результат от анонимной внутренней функции в переменной, а затем вернуть эту переменную из функции findIt, как показано ниже.

var myArray=[ 
 
    { 
 
     "name":"Joe", 
 
     "zip":90210 
 
    }, 
 
    { 
 
     "name":"Bill", 
 
     "zip":94109 
 
    } 
 
]; 
 

 
function findIt(myArray,target) { 
 
    var answer; 
 
    myArray.forEach(function (person) { 
 
     if (person.name === target) { 
 
      answer = person.zip; 
 
     } 
 
    }); 
 
    
 
    return answer; 
 
} 
 
var zip=findIt(myArray,"Joe"); 
 
console.log(zip);

+0

Мне очень нравится этот ответ. Другие ответы информативны, и я рассмотрю их более подробно, но это самое простое решение. Спасибо! –

+0

@EamonnGormley 'forEach' - это неправильная вещь для поиска в структуре данных. 'forEach' будет проходить через весь массив независимо от того, как быстро будет найдено совпадение. См. Мой ответ для гораздо лучшего решения. – naomik

+0

Также, если одно и то же имя появляется в данных более одного раза, последнее совпадение всегда будет возвращено. Я считаю это поведение ошибкой. – naomik

3

Вы ничего не return ИНГ от вашей функции

function findIt(myArray,target) { // <--------------------┐ 
    myArray.forEach(function (person) {   // <--┐ | 
     if (person.name === target) {   // | | 
      return person.zip; // returns this func ---┘ | 
     }          //  | 
    });           //  | 
    // you need a return for this function --------------┘ 
} 

В любом случае, даже если вы исправить это, ваша функция все еще может использовать немного работы. forEach собирается перебирать весь набор данных, даже если он находит совпадение по первому элементу. forEach - это неправильная вещь для использования здесь.


Действительно простая вещь, которую вы можете использовать, - Array.prototype.find. Array.prototype.find прекратит итерирование данных, как только будет найдено первое совпадение.

var myArray=[ 
 
    { 
 
    "name":"Joe", 
 
    "zip":90210 
 
    }, 
 
    { 
 
    "name":"Bill", 
 
    "zip":94109 
 
    } 
 
] 
 

 
const findIt = (data, target) => { 
 
    // use Array.prototype.find 
 
    let {zip} = myArray.find(({name})=> name === target) || {} 
 
    return zip 
 
} 
 

 
console.log(findIt(myArray, 'Joe')) 
 
// => 90210 
 

 
console.log(findIt(myArray, 'unmatched name')) 
 
// => undefined

Но если вы предпочли бы реализовать функцию себя в качестве учебного упражнения, которые будут выглядеть следующим образом. Обратите внимание: этот код будет работать как Array.prototype.find тем, что он вернется, как только будет найдено первое совпадение.

var myArray=[ 
 
    { 
 
    "name":"Joe", 
 
    "zip":90210 
 
    }, 
 
    { 
 
    "name":"Bill", 
 
    "zip":94109 
 
    } 
 
] 
 

 
// implement generic find 
 
const find = f => ([x,...xs]) => { 
 
    if (x === undefined) 
 
    return undefined 
 
    else if (f(x)) 
 
    return x 
 
    else 
 
    return find (f) (xs) 
 
} 
 

 
// implement your function using find 
 
const findIt = (data, target) => { 
 
    let {zip} = find (({name})=> name === target) (data) || {} 
 
    return zip 
 
} 
 

 
console.log(findIt(myArray, 'Joe')) 
 
// => 90210 
 

 
console.log(findIt(myArray, 'unmatched name')) 
 
// => undefined

Это разумный способ написать findIt потому что вместо относительно себя пробегаем по списку данных, или возвращает соответствующий объект, он просто вызывает обобщенную функцию (find), который могут быть повторно использованы многими другими функциями.


ES5

Как любезность, я обеспечиваю пре-ES6 кода выше

var myArray=[ 
 
    { 
 
    "name":"Joe", 
 
    "zip":90210 
 
    }, 
 
    { 
 
    "name":"Bill", 
 
    "zip":94109 
 
    } 
 
] 
 

 
// implement generic find 
 
function find (f) { 
 
    return function(xs) { 
 
    if (xs[0] === undefined) 
 
     return undefined 
 
    else if (f(xs[0])) 
 
     return xs[0] 
 
    else 
 
     return find (f) (xs.slice(1)) 
 
    } 
 
} 
 

 
// implement your function using find  
 
function findIt (data, target) { 
 
    var p = find (function(x) { return x.name === target }) (data) || {} 
 
    return p.zip 
 
} 
 

 
console.log(findIt(myArray, 'Joe')) 
 
// => 90210 
 

 
console.log(findIt(myArray, 'unmatched name')) 
 
// => undefined

1

A версия обратного вызова, только для fun:

function findIt(myArray,target, cb) { 
    myArray.forEach(function (person) { 
      if (person.name == target) cb(person.zip) 
    }); 
} 

Как:

findIt(myArray,"Joe", function(zip){ alert(zip) }); 

Обновление:

Пример нахождения и использования одного значения почтового индекса в то время, со следующим массивом.

var myArray=[ 
    { 
     "name":"Joe", 
     "zip":90210 
    }, 
    { 
     "name":"Bill", 
     "zip":94109 
    }, 
    { 
     "name":"Joe", 
     "zip":12345 
    } 
]; 

Теперь он должен предупредить дважды один раз для «90210» и второй раз для «12345»

+0

можете ли вы предоставить прецедент для продолжения (обратного вызова) для этого чисто синхронного кода? кроме «просто для удовольствия», я имею в виду ... – naomik

+0

@naomik уверен, позвольте привести пример – jmunsch

+0

@naomik у вас есть что-то еще в виду? – jmunsch

0

forEach реализуется как парованием, это доза не возвращать допустимое значение (не определено).

forEach(array, callback) { 
    for (var index in array) { 
     callback(array[index]); 
    } 
} 

вы хотите вернуть нужное значение сразу найти его, так что попробуйте это:

function findIt(myArray,target) { 
    for (var index in myArray) { 
     if (myArray[index].name === target) { 
      return myArray[index].zip; 
     } 
    } 

} 

если массив имеет много элементов, этот пример остановится после того, как найти одну согласованную, а не сканирование Все детали.

Смежные вопросы