Частичное приложение window.onblur и console.log с привязкой
Я читал некоторые посты javascript и наткнулся на этот ответ.
В основном, в ответе, плакат сказал, что вы можете установить
window.onblur = myBlurFunction
только если myBlurFunction
это функция, которая не нуждается в аргументах, переданных ей
Я собирался прокомментировать, что можно было использовать bind
выполнить частичное применение для функций, требующих аргументов, но когда я пытался
var myBlurFunction = console.log.bind(console,'blur');
window.onblur = myBlurFunction;
размытие окна не печатало строку "размытие", а вместо этого печатало то, что кажется размытым объектом
blur blur { target: Window → window-onblur-not-working, …
Кто-нибудь знает, почему этот подход не работает?
Что я действительно ищу в своем вопросе, так это то, почему функция-обработчик события получает событие в качестве аргумента?
window.onblur = function(event){console.log(event)}
Я никогда не видел никакой документации, которая упоминает или объясняет параметр события.
Кроме того, как связанный параметр переопределяется? Обычно, когда значение привязано к параметру функции, любые дополнительные аргументы будут назначены следующим параметрам:
var f = function(arg1,arg2){console.log(arg1,arg2)};
g = f.bind(null,1);
g(); // 1 undefined
g(2); // 1 2
g.call(null,2); // 1 2
1 ответ
Цитируя bind()
страница на MDN:
Метод bind() создает новую функцию, которая при вызове имеет
this
ключевое слово, установленное на указанное значение, с заданной последовательностью аргументов, предшествующей любому указанному при вызове новой функции.
Давайте разделим эти две концепции и затем объясним их вместе в вашем примере.
Изменение этого контекста
Это адаптация примера на странице MDN (обещаю, что это просто!):
// This assignment is equivalent to 'window.x' or 'var x' in the global scope
this.x = "global!";
var obj = {
x: "not global!",
getX: function() {
return this.x;
}
};
// Running inside the object's scope, returns obj.x
obj.getX();
//=> "not global!"
// Assign the scoped function (obj.getX) to a global variable
var retrieveX = obj.getX;
// Running in the global scope, returns window.x
retrieveX();
//=> "global!"
// Binds the 'retrieveX' function to run inside the object's scope
var boundedRetrieveX = retrieveX.bind(obj);
// Running inside the specified 'obj' scope, returns obj.x
boundedRetrieveX();
//=> "not global!"
Из этого мы получаем, что прохождение obj
в качестве аргумента меняет какой контекст this
относится к.
На вашем примере вы делаете что-то вроде этого:
console.log.bind(console); // The second argument doesn't matter for now
Итак, вы говорите console.log
что любые случаи this
являются ссылкой на console
контекст. Что, я полагаю, хорошо, не должно причинить много вреда.
Предстоящие аргументы
Опять же, адаптируясь из примера страницы MDN:
function list() {
// Simply convers the arguments list into an Array, then returns it
return Array.prototype.slice.call(arguments);
}
// Example usage
list(1, 2, 3);
//=> [1, 2, 3]
// Using 'bind' to prepend to (append to the start of) the arguments list
// Note that, because 'this' context doesn't matter, the first argument is null
var betterList = list.bind(null, 98);
// Passing no arguments, it returns an array with only 98
// This is similar to '[98].concat([])'
betterList();
//=> [98]
// Passing arguments, it appends 98 to the start of the array
// Again, this is similar to '[98].concat([1,2,3])'
betterList(1, 2, 3);
// [98, 1, 2, 3]
// The parameters can go on indefinitely. They will all be added to the start of the arguments list in order
var bestList = list.bind(null, 98, 99, 100);
bestList(1, 2, 3);
//=> [98, 99, 100, 1, 2, 3]
Функция list
поворачивает объект, похожий на массив arguments
, который содержит все аргументы, переданные функции, в фактический массив.
С bind()
, мы добавляем значения в начало этого списка аргументов, так что для функции кажется, что они уже были переданы таким образом.
Ваш код выглядит примерно так:
console.log.bind(console, "blur");
Игнорируя первый аргумент, вы добавляете аргументы, отправленные console.log
(который в данном случае является ответом на событие) с "blur"
, Что тоже не вредно, просто не очень полезно.
Последние мысли
Итак, вот скриншот моей игры с аргументами. Первый аргумент, который указывает контекст для this
, установлен в null
как в примере выше, потому что здесь это не имеет значения. И я передал длинный список аргументов после того, как onblur
ответ на событие.
Как вы можете видеть, даже несмотря на то, что я добавил кучу материала к ответу, объект Event (не объект размытия! Ха-ха) все еще там.
Вот почему это "не" работает. Работает по-своему. Это может быть не то, что вы ожидали.
Вы по-прежнему можете использовать подходы, представленные в связанном вопросе, такие как
window.onblur = () => console.log("blur");
Решения, которые являются менее сложными и фактически делают то, что вы ожидаете от них