Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
зачем зацикливаться на коде вообще?Уже откровенный троллинг, погляжу. Ок, спасибо за дискуссию.
Я говорил о том, что кроме кода есть масса критериев отбора.Я это чуть ли не в каждом комменте твержу. Но не задавать вопросы по коду на собеседовании разработчика – это ОЧЕНЬ странный подход. Возможен, только когда вообще нет никого, способного оценить его ответы (и нет никого, кто мог бы погуглить подобные задачки с формальными ответами).
Очевидно, надо почитать лучшие наработки и ввести кодстайл.Спасибо, Кэп. А кто будет читать наработки и вводить кодстайл, если нет спецов?
Можно позадавать вопросы, как работает то или иноеТак вопросы из поста именно на это нацелены! Просто вместо сложного кода реальных библиотек/фреймворков взяты искуственные примеры, чтоб лишнее не путалось.
Например, дать тестовое заданиеПо себе скажу, что тестовое задание делать очень лениво. Обычно проще пойти на другое собеседование. Надо очень вкусные условия предлагать, либо иметь большой поток желающих.
Logger = function(logFn) {
_logFn = logFn;
...
}
var x будет «выполнен» одновременно с function x() {}. Слово «выполнен» я взял в кавычки, потому что объявления не выполняются.Вообще-то интерпретатор выполнит сначала function x() {};, затем var x; и только потом x=1;
Не лучше ли выяснить насколько человек целеустремленный и любознательныйА одно другому не мешает.
Я обучал нескольких ребят проходить интервью ещё когда они не были даже junior разработчиками.А вот это как раз опровергает ваши доводы. Если человек, освоивший хотя бы такие «плохие» тестовые примеры уже может работать с этим языком – значит эти примеры как раз и проверяют в той или иной степени знание языка.
Понимание этого всего не спасает от плохого кода, ошибок такого рода и т.п.Эээ… Значит, это было не понимание, а тупое заучивание шаблонов.
obj внутри функции локальна, но суть в том, что ей присваивают указатель на новый объект — {a: 2}.var obj = {
a: 1
};
(function(obj) {
obj.a = 2;
})(obj);
console.log(obj.a);//, то здесь будет «2».
Передаётся значение — «указатель» на объект, но не ссылка. (если исходить из тепрминов C/C++).
* — зато аналогия между . в javascript и -> в С/С++ — полная.function foo(arg) { arg = 5; }
var bar = 10;
foo(bar);
function foo(arg) { arg = 5; }
var bar = new Number(10);
foo(bar);
bar все равно не стал равен 5.function foo(arg) { arg = {value: 5}; }
var bar = {value: 10};
foo(bar);
и даже вот так переменная не изменилась. Такое поведение — это и есть передача по значению.function foo(arg) { arg.value = 5; }
var bar = {value: 10};
foo(bar);
то я вам скажу, что изменилось содержимое объекта, но переменная все еще продолжает указывать на тот же самый объект. Это все равно передача по значению.function foo(object, value) {
object.valueOf = function () {
return value;
};
}
var bar = new Number(0);
foo(bar, 100);
bar + 1; // 101
Logger = function(logFn) {
this.log = function(message) {
logFn(new Date() + ": " + message);
};
}
this равен window (или, к примеру, console). Достаточно обернуть встроеную функцию в свою, чтобы это исправить. Например, такой аргумент сработает.console.myLog = function(message) { console.log(message) };
var logger2 = new Logger(console.myLog);
logger2.log("Hi!");
logger2.log("Wazzup?");
// Sat Oct 04 2014 09:30:04 GMT+0300 (EEST): Hi!
// Sat Oct 04 2014 09:30:04 GMT+0300 (EEST): Wazzup?
bind(), либо function. Можно пойти другим путём и байндить встроенные функции к window внутри тела log. Функция isNative взята из внешних источников.var Logger = function(logFn) {
if (isNative(logFn)) {
this.log = function(message) {
logFn.bind(window)(new Date() + ": " + message);
};
} else {
this.log = function(message) {
logFn(new Date() + ": " + message);
};
}
}
var logger3 = new Logger(alert);
logger3.log("Hi!");
logger3.log("Wazzup?");
console не пройдёт (и другими встроенными объектами, содержащими встроенные своёства наподобие console.log. Я не придумал, как это обойти.Однако оба таких решения не самые изящные, так как нам везде придётся использовать либо bind(), либо function.
Однако такой трюк с console не пройдёт (и другими встроенными объектами, содержащими встроенные своёства наподобие console.log. Я не придумал, как это обойти.
А чем вам bind не изящный?
Logger увидит такой код, ему придётся потратить время, чтобы разобраться, как работает конструктор, что неоправданно усложняет код. Я попытался скрыть детали реализации. :)Передавать в логгер вместе с функцией скоп вызова?
bind(), так как с ним знакомо несравнимо большее количество людей, чем с Logger (смысл-то остаётся такой же).Когда человек, который хочет инициализировать объект Logger увидит такой код, ему придётся потратить время, чтобы разобраться, как работает конструктор, что неоправданно усложняет код. Я попытался скрыть детали реализации. :)
Если я правильно разобрался, то это лишь касается только встроенных функций, так как такие функции ожидают, что this равен window (или, к примеру, console). Достаточно обернуть встроеную функцию в свою, чтобы это исправить. Например, такой аргумент сработает.Неверно. Любой метод ожидает корректного
this, не только встроенный.var obj = {
value: 5,
foo: function() { console.log(value); }
};
obj.foo(); // 5
var foo = obj.foo();
foo(); // undefined
var obj = {
value: 5,
foo: function() { console.log(this.value); } // [исправлено]
};
obj.foo(); // 5
var foo = obj.foo; // [исправлено]
foo(); // undefined
var log = console.log;
log('Hello'); // TypeError: Illegal invocation
log.bind(console)('World'); // => World
bind() так называется: он как бы склеивает методы.[function(){}, function(){}].forEach(Function.prototype.call.call)[function(){console.log(1)}, function(){console.log(2)}].forEach(Function.prototype.call.call.bind(Function.prototype.call))
[
function(){console.log(1)},
function(){console.log(2)}
].forEach(Function.prototype.call.call, Function.prototype.call)[ function(){console.log(1)}, function(){console.log(2)} ].forEach(Function.prototype.call, Function.prototype.call)
call вызывать дважды. Первый раз мы получаем тело объекта-функции Function.prototype.call. Второй call опять же получает себя, так как мы обращаемся к тому же самому методу но через экземпляр нашего объекта-функции.Теперь очень ясно видно, почему bind() так называется: он как бы склеивает методы.
Любой метод ожидает корректного this, не только встроенный.
var obj = {
value: 5,
foo: function() { console.log(value); }
foo2: function(msg) { console.log(msg); }
};
А всё потому что при вызове logger.log(), контекст выполнения функции — loggerЭто вы зря так говорите, может показаться, будто контексты выполнения неявно наследуются — а это не так.
logger.log() функция, обозванная logFn вызывается без контекста (или в контексте window, что примерно одно и то же) — и проблема именно в этом.logger.log нам вообще не интересен, потому что эта функция к своему контексту не обращается.setTimeout будет отличаться от setInterval более длинным промежутком между вызовами. Это удлинение вызвано тем, что setInterval начинает отсчет сделующего интервала сразу же после окончанию предыдущего — а setTimeout еще надо успеть вызвать повторно.function Class1 () {
var a = 1;
this.log = function () {
console.log(a);
}
}
var obj = new Class1();
function Class2 (func) {
this.log2 = function() {
func();
}
}
var obj2 = new Class2(obj.log);
obj.log();
obj2.log2();
1
1
function Class1 () {
this.a = 1;
this.log = function () {
console.log(this.a);
}
}
function Class1 () {
this.a = 1;
this.log = function () {
if (!(a instanceof Class1))
throw TypeError ("Illegal invocation");
console.log(this.a);
}
}
var obj = new Class1();
function Class2 (func) {
this.log2 = function() {
func();
}
}
var obj2 = new Class2(obj.log);
obj.log();
obj2.log2();
if (!(this instanceof Class1)), конечно жеconsole.log от контекста console. Я не силён в C+, но ответ на все вопросы и всё такое существует.Удивлён, если первый класс заменить на ... то obj2.log2 выводит undefined, то есть this.a не попадает в замыкание?this.a не попадает в замыкание, потому что это не локальная переменная. У вложенной функции может быть свой контекст — и свой this. Для того, чтобы передать this в замыкание, часто первой строчкой функции пишут var that = this и дальше используют переменную that (ни разу не встречали такого?)(function() { f(); f = function() { console.log(1); } })() function f() { console.log(2) } f();
Что мы увидим в консоли?
Ответ
Объявленная в gs function f() всплывёт, соответственно при вызове f внутри анонимной функции мы увидим не ReferenceError, как кто-то мог предположить, а двойку в консоли, при повторном вызове переменная f уже ссылается на функцию которая печатает 1.
var f) или объявление функции (function f). Ничего из этого в анонимной функции нет.f = function() было написано var — то все работало бы так, как вы написали.for(var i = 0; i < 5; i++)
console.log(i)
var i = undefined;
for(i = 0; i < 5; i++)
console.log(i);
JavaScript. Вопросы на собеседовании