Function sees only three arguments

This is a simplified code that runs on Node.js crawler and it gets all data. But how do I insert inside the "callback": function value of var "i" from cycle for(var i=0... When I'm adding name: datas[i].name it returns an error:

TypeError: Cannot read property 'undefined' of undefined

var Crawler = require("crawler").Crawler;
var crawler = new Crawler;

var datas  = [
{name: 'John', url: 'john025'},
{name: 'Jim', url: 'jim04567'}
];

function crauler(done) {
for (var i = 0; i < datas.length; i++) {
    var link = 'http://somesite.com/' + datas[i].url;
    crawler.queue([{
        "uri": link,
            // inside this func
                        "callback": function (error, result, $, datas, i) {
            var arr = $('.blogpost').map(function (index) {
                var str = $(this).attr('href');
                var object = {
                    numb: str,
                    name: datas[i].name
                };
                return obj; 
            }).get().join(',');
            done(arr);
} }]) }; };

crauler (function (arr) {
console.log(arr);
});

You can't pass datas and i into callback functions like this. What arguments that the callback functions will be called with are up to the caller, you don't have the control of it.

You're seeing "TypeError: Cannot read property 'undefined' of undefined" because you want your callback function to have datas and i as parameters; but the caller will call the callback with the first 3 arguments only [crawler callback reference], so the datas and i are undefined.

Therefore, you should remove the datas and i from in line:

"callback": function (error, result, $, datas, i) {

Because datas is defined in the outer scope of the callback function, the callback can access datas without any special treatment. For the variable i, it's a little bit tricky as mentioned in other answers, so you need to create a closure for it.

So, your callback function definition should be something looks like the following:

"callback": (function(i) { // create closure for i
    return function (error, result, $) { // no more datas and i here
        var arr = $('.blogpost').map(function (index) {
            var str = $(this).attr('href');
            var object = {
                numb: str,
                name: datas[i].name // access datas as it
            };
            return obj; 
        }).get().join(',');
        done(arr);
    }
})(i)

You're trying to create a closure around i inside of a loop which is causing you problems. This answer should help you:

Javascript closure inside loops - simple practical example

You need a closure to capture the values, this is one way to solve the problem. Read up on closures.

Javascript

var Crawler = require("crawler").Crawler;
var crawler = new Crawler;

var datas = [{
    name: 'John',
    url: 'john025'
}, {
    name: 'Jim',
    url: 'jim04567'
}];

function queue(link, i) {
        crawler.queue([{
            "uri": link,
            // inside this func
            "callback": function (error, result, $, datas, i) {
                var arr = $('.blogpost').map(function (index) {
                    var str = $(this).attr('href');
                    var object = {
                        numb: str,
                        name: datas[i].name
                    };
                    return obj;
                }).get().join(',');
                done(arr);
            }
        }]);
}

function crauler(done) {
    for (var i = 0; i < datas.length; i++) {
        var link = 'http://somesite.com/' + datas[i].url;
        queue(link, i);
};

crauler(function (arr) {
    console.log(arr);
});