Частичное приложение 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");

Решения, которые являются менее сложными и фактически делают то, что вы ожидаете от них

Другие вопросы по тегам