`този` обект в require().function()

Занимавайки се с библиотеката с възли robots, забелязах, че

var robots = new require('robots').RobotsParser();

се различава от

var robots = new (require('robots')).RobotsParser();

Първият require се проваля, оплаквайки се, че this.someFunction() не съществува, докато вторият успява. По някаква причина обектът this в първия ред по-горе очевидно се отнася до глобалния обект, докато във втория ред е обвързан с модула robots. Защо?

Грешката, която получавам е:

/home/user/crawler/lib/robots/lib/parser.js:44
    this.setUrl(url, after_parse);
         ^
TypeError: Object #<Object> has no method 'setUrl'

setUrl е действителното someFunction, споменато в примера.


person davide    schedule 14.05.2015    source източник
comment
Гласувам да затворя този въпрос като извън темата, защото OP не следваше инструкциите за използване за репото и след това е изненадан, че не работи.   -  person Mathletics    schedule 14.05.2015
comment
възможен дубликат на Как се изисква работа с нов оператор в възел .js?   -  person Leonid Beschastny    schedule 14.05.2015
comment
@Mathletics Има грешна употреба, но все още демонстрира конкретен случай на неочаквано поведение, на който може да се отговори. IMO да го нарече извън темата е пресилено.   -  person E_net4 the curator    schedule 14.05.2015
comment
@E_net4 това е красотата на системата за гласуване: аз имам само един глас. Във всеки случай беше открита истинска измама.   -  person Mathletics    schedule 14.05.2015
comment
@davide няма връзка между require и this; require е просто функция като всяка друга в JS.   -  person Mathletics    schedule 14.05.2015


Отговори (2)


var robots = new require('robots').RobotsParser();

се анализира като

var robots = (new require('robots')).RobotsParser();

т.е. опитва се да извика метода RobotsParser на екземпляр require(). Не това, което искахте!

person Scimonster    schedule 14.05.2015

Първият ред прави извикване на конструктор на require, което ефективно променя препратката this в обхвата на библиотеката, за да сочи към нов, предполагаем екземпляр на require. Това е неправилно и require винаги трябва да се извиква като обикновена функция. Добавянето на скоби (както във втория ред) изчиства проблема, тъй като вместо това ще създаде нов екземпляр на RobotsParser.

person E_net4 the curator    schedule 14.05.2015
comment
Благодаря ти @E_net4. Объркан съм, защото операторът за членски достъп (.) има по-висок приоритет от new, но това не изглежда да е проблем за приоритета на оператора. Можете ли да ме насочите към някои документи, които осветляват това? - person davide; 14.05.2015
comment
Вашият проблем изглежда е свързан с приоритета на оператора. Записването на new foo().a() ще извика функцията член a на нов екземпляр на foo. Ако се чудите как работи this, едно малко търсене ще ви отведе до някои добри източници. Разгледайте този. - person E_net4 the curator; 14.05.2015
comment
Благодаря ви, прочетох свързаната статия за JS Is Sexy. И все пак не разбирам защо в new foo().a() функцията a се извиква на новото копие на foo вместо на старото. Ако new има по-нисък приоритет от ., защо функцията член a се изпълнява след new? Документите на MDN изглеждат плитки по този конкретен детайл. - person davide; 14.05.2015
comment
Той няма с по-нисък приоритет. Поведението е добре дефинирано и е обратното на това, което си мислите. Освен това също няма стар екземпляр, а само неволно създаден нов. - person E_net4 the curator; 14.05.2015