Может кто-нибудь объяснить мне этот код JavaScript, который определяет некоторые переменные и проходит через них? - PullRequest
0 голосов
/ 20 ноября 2011

Я слежу за этим уроком: http://vimeo.com/16961179, который учит вас, как создавать представления и частичные с помощью express.js :

var products = [
{
    id: 1,
    name : 'Mac Book Pro',
    description: 'Apple 13 inch Mac Book Pro notebook',
    price: 1000
},
{
    id: 2,
    name : 'iPad',
    description: 'Apple 64GB 3G iPad',
    price: 899
}
];

module.exports.all = products;

module.exports.find = function(id) {
    id = parseInt(id, 10);
    var found = null;
    productloop: for(product_index in products) {
        var product = products[product_index];
        if (product.id == id) {
            found = product;
            break productloop;
        }
    };
    return found;
}

В уроке автор мало что объясняет в этой части. Я особенно запутался в части цикла. Кто-нибудь может мне это объяснить (я новичок в JavaScript)?

Я понимаю переменную products в верхней части, но она выглядит как массив, в котором есть другие массивы.

Ответы [ 4 ]

2 голосов
/ 20 ноября 2011

Функция ищет продукт по идентификатору продукта.

  • Цикл устанавливает последовательно product для каждого продукта в массиве продуктов.
  • Сравнивает идентификатор этого продукта стот, который передан в функцию.
  • Если он равен, он выходит из цикла (yay goto) и возвращает произведение (правдиво).
  • Если он выходит из цикла нормально, это означает, что продукт не был найден, и он вернет ноль (фальси).
1 голос
/ 20 ноября 2011

Products - массив, содержащий два объекта. Некоторые люди могут называть их «ассоциативными массивами», но они просто объекты. У них есть «свойства» (например, id) и «значения»:

var products = [{
    id: 1,
    name : 'Mac Book Pro',
    description: 'Apple 13 inch Mac Book Pro notebook',
    price: 1000
},{
    id: 2,
    name : 'iPad',
    description: 'Apple 64GB 3G iPad',
    price: 899
}];

module.exports - это объект, который ваша программа узла увидит, когда вы выполните require('./products.js'):

module.exports = {

    // just pass along the whole array
    all: products,

    // method to find a product by id
    find: function(id){
        return products.filter(function(product){
            return product.id == id
        })[0] // we return the first element, at index zero
    }
}

Я заменил цикл for in на метод filter , здесь все должно проясниться. Он зациклится на массиве products и выполнит функцию для каждого из них - если результат true, элемент добавляется к результату, в противном случае он игнорируется.


Вот как должен выглядеть этот модуль при использовании Express:

var products = require('./products.js')

app.get('/products', function(req, res){
    // get the whole products array
    products.all
    // render page...
})
app.get('/products/:id', function(req, res){
    // get product with id ':id' from URL (http://mysite.com/products/25)
    var p = products.find(req.params.id)
    // render page...
})
1 голос
/ 20 ноября 2011

Прежде всего, это ужасный код.Это может сломаться при малейшем изменении.Давайте начнем с первой строки.

var products = [

Объявляет переменную в глобальном контексте.Постарайся избежать этого.Все, что происходит в глобальном контексте, может сломаться.Кроме того, инкапсуляция данных помогает повысить модульность кода, что, в свою очередь, позволяет повторно использовать код.

Давайте рассмотрим функцию find ():

module.exports.find = function(id) {
    id = parseInt(id, 10);
    var found = null;
    productloop: for(product_index in products) {
        var product = products[product_index];
        if (product.id == id) {
            found = product;
            break productloop;
        }
    };
    return found;
}

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

Так что это (var product = products[product_index];) объявление фактически не объявляет новую переменную каждую итерацию.

Далее.

product.id == id

Операторы == и! = Выполняют приведение типов перед сравнением.Это плохо, потому что это заставляет '\ t \ r \ n' == 0 быть верным.Это может маскировать ошибки типа.В случае функции find () оператор == не приводит к ошибке, но это место, где ошибка может появиться при изменении кода.Всегда используйте оператор ===.

for(product_index in products) 

Оператор for in позволяет циклически проходить имена всех свойств объекта.К сожалению, он также просматривает все свойства, которые были унаследованы через цепочку прототипов.У этого есть плохой побочный эффект обслуживания функций метода, когда интерес к свойствам данных.Если программа написана без осознания этой ситуации, она может потерпеть неудачу.

Тело каждого оператора for in должно быть заключено в оператор if, выполняющий фильтрацию.Он может выбирать для определенного типа или диапазона значений, или он может исключать функции, или он может исключать свойства из прототипа.Например,

for (name in object) {
    if (object.hasOwnProperty(name)) {
        ....
    }

}

В вашем коде «products» - это массив, поэтому вы можете быть уверены, что у него нет дополнительных свойств.Но!Products - это глобальная переменная, поэтому в действительности это может быть что угодно.

Я немного переписал функцию и объяснил, что делает этот код.

module.exports.find = function(id) {
    var found = null,
       product;
    id = parseInt(id, 10);        
    for (product_index in products) {
        if (products.hasOwnProperty(product_index)){
            product = products[product_index];
            if (product.id === id) {
                found = product;
                break;
            }
        }
    };
    return found;
}

Все просто.Функция принимает идентификатор продукта в качестве аргумента (function(id)), превращает его в число (id = parseInt(id, 10);).Затем проходит через массив продуктов один за другим с циклом (for(product_index in products)), проверяя равенство переданного идентификатору функции и идентификатору текущего продукта (if (product.id == id)).Если они равны, прекращает итерацию (break;), присваивает значение текущего произведения переменной «found» (found = product;) и возвращает результат вызывающей функции (return found;).

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

1 голос
/ 20 ноября 2011

Будет ли это более читабельным для вас выражается так:

var products = [
{
    id: 1,
    name : 'Mac Book Pro',
    description: 'Apple 13 inch Mac Book Pro notebook',
    price: 1000
},
{
    id: 2,
    name : 'iPad',
    description: 'Apple 64GB 3G iPad',
    price: 899
}
];

module.exports.all = products;

module.exports.find = function(id) {
    var i, product,
    nProducts = products.length;

    id = parseInt(id, 10);
    for(i = 0; i < nProducts; ++i) {
        product = products[i];
        if (product.id === id) {
            return product;
        }
    }
    return null;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...