Hoisting
Hoisting — всплытие переменных объявленных в функции.Здесь можно подробно узнать о том как это бывает.
А вот интересный вопрос:
(function() { f(); f = function() { console.log(1); } })() function f() { console.log(2) } f();
Что мы увидим в консоли?
function f() всплывёт, соответственно при вызове f внутри анонимной функции мы увидим не ReferenceError, как кто-то мог предположить, а двойку в консоли, при повторном вызове переменная f уже ссылается на функцию которая печатает 1.
Результат:
< (function() { f(); f = function() { console.log(1); } })() function f() { console.log(2) } f(); > undefined 2 1
Если вы сходу уловили подвох предыдущей задачи — не обольщайтесь. Вот ещё интересный пример кода:
(function() { var x = 1; function x() {}; console.log(x); })()
Что теперь мы увидим в консоли?
var. Поэтому интерпретатор сначала выполнит function x() {};, а затем var x = 1;
< (function() {
var x = 1;
function x() {};
console.log(x);
})()
> undefined
1
Ну и напоследок. Напомню советы Дугласа Крокфорда: избегать слабых сторон языка и использовать сильные и использовать JSLint.
Чтобы не наткнуться на такие сюрпризы можно взять за привычку самому выносить var в начало функции и объявлять функцию через function expression
Передача по ссылке
Наверное все знают что все объекты передаются в javascript по ссылке:
var obj = { a: 1 } (function(obj) { obj = { a: 2 }; })(obj); console.log(obj.a);
Не знаю как вы, а я засыпался на этом вопросе. Я точно знал что объект не измениться после вызова функции, но объяснить почему так и не смог.
{a : 2}, ссылка на который попадает в локальную переменную obj, но переменная из верхнего скоупа будет всё так же ссылаться на старый объект. Контекст выполнения
Контекст выполнения функции — мощный и выразительный механизм, если умело его использовать. Правда есть несколько моментов о которых не стоит забывать. Простой пример. Рассмотрим класс который логгирует некие действия.
Logger = function(logFn) { _logFn = logFn; this.log = function(message) { _logFn(new Date() + ": " + message); } } var logger = new Logger(console.log); logger.log("Hi!"); logger.log("Wazzup?");
Что будет в консоли? Как починить?
TypeError: Illegal invocationА всё потому что при вызове
logger.log(), контекст выполнения функции — logger
Чтобы починить можно вспомнить про встроенные методы функций .apply(), .call(), .bind()
< rightLogger = new Logger(console.log.bind(console)) > Logger {log: function} < rightLogger.log("It's works") > Sat Oct 04 2014 00:32:49 GMT+0400 (MSK): It's works
ссылка на оригинал статьи http://habrahabr.ru/post/239065/
Добавить комментарий