Как передать асинхронную функцию другой функции и выполнить ее? [Дубликат]

SQL Select не чувствителен к регистру.

Эта ссылка может показать вам, как сделать регистр чувствителен к регистру: http://sqlserver2000.databases.aspfaq.com/how-can-i- макияж мои-SQL-запросы регистра-sensitive.html

985
задан T.J. Crowder 11 July 2017 в 18:32
поделиться

10 ответов

Что вы должны знать о this

this (иначе говоря, «контекст») - это специальное ключевое слово внутри каждой функции, и его значение зависит только от того, как была вызвана функция, а не как / когда / где он был определен. Лексические области не затрагиваются, как и другие переменные. Вот несколько примеров:

function foo() { console.log(this); } // normal function call foo(); // `this` will refer to `window` // as object method var obj = {bar: foo}; obj.bar(); // `this` will refer to `obj` // as constructor function new foo(); // `this` will refer to an object that inherits from `foo.prototype`

Чтобы узнать больше о this, посмотрите документацию MDN.

Как обратиться к correct this

Не использовать this

Вы действительно не хотите получать доступ к this в частности, но как . Вот почему простое решение - просто создать новую переменную, которая также относится к этому объекту. Эта переменная может иметь любое имя, но обычными являются self и that.

function MyConstructor(data, transport) { this.data = data; var self = this; transport.on('data', function() { alert(self.data); }); }

Поскольку self является нормальной переменной, она подчиняется лексическим правилам области и доступна внутри обратного вызова. Это также имеет то преимущество, что вы можете получить доступ к значению this самого обратного вызова.

Явно установить this обратного вызова - часть 1

. Может показаться, что у вас есть не контролируйте значение this, потому что его значение устанавливается автоматически, но на самом деле это не так.

Каждая функция имеет метод документа MDN , который возвращает новую функцию с this, привязанную к значению. Функция имеет то же поведение, что и тот, который вы назвали .bind, только то, что this было установлено вами. Независимо от того, как и когда эта функция вызывается, this всегда будет ссылаться на переданное значение.

function MyConstructor(data, transport) { this.data = data; var boundFunction = (function() { // parenthesis are not necessary alert(this.data); // but might improve readability }).bind(this); // <- here we are calling `.bind()` transport.on('data', boundFunction); }

В этом случае мы привязываем обратный вызов this к значению MyConstructor 'this.

Примечание. При связывании контекста для jQuery вместо этого используйте jQuery.proxy [docs]. Причина этого заключается в том, что вам не нужно сохранять ссылку на функцию при отмене обратного вызова события. jQuery обрабатывает это внутренне.

ECMAScript 6: Используйте функции стрелок

В ECMAScript 6 представлены функции стрелок, которые можно рассматривать как лямбда-функции. У них нет собственной привязки this. Вместо этого this просматривается в области видимости как обычная переменная. Это означает, что вам не нужно называть .bind. Это не единственное особое поведение, которое у них есть. Дополнительную информацию см. В документации MDN.

function MyConstructor(data, transport) { this.data = data; transport.on('data', () => alert(this.data)); }

Установите this обратного вызова - часть 2

Некоторые функции / методы, которые принимают обратные вызовы, также принимают значение, к которому должен обращаться обратный вызов this. Это в основном то же самое, что и привязывать его самостоятельно, но функция / метод делает это за вас. jQuery.proxy [docs] - такой метод. Его подпись:

array.map(callback[, thisArg])

Первым аргументом является обратный вызов, а второй аргумент - значение this. Вот надуманный пример:

var arr = [1, 2, 3]; var obj = {multiplier: 42}; var new_arr = arr.map(function(v) { return v * this.multiplier; }, obj); // <- here we are passing `obj` as second argument

Примечание: Если вы можете передать значение для this, обычно упоминается в документации к этой функции / методу. Например, метод $.ajax jQuery [docs] описывает параметр, называемый context:

Этот объект станет контекстом всех обратных вызовов, связанных с Ajax.

Общая проблема: использование объектных методов в качестве обработчиков обратных вызовов / событий

Другим распространенным проявлением этой проблемы является то, что объектный метод используется как обработчик обратного вызова / события , Функции являются первоклассными гражданами в JavaScript, а термин «метод» - просто разговорный термин для функции, которая является значением свойства объекта. Но эта функция не имеет конкретной ссылки на ее «содержащий» объект.

Рассмотрим следующий пример:

function Foo() { this.data = 42, document.body.onclick = this.method; } Foo.prototype.method = function() { console.log(this.data); };

Функция this.method назначается как обработчик события click , но если щелкнуть document.body, зарегистрированное значение будет undefined, потому что внутри обработчика события this ссылается на document.body, а не на экземпляр Foo. Как уже упоминалось в начале, то, что относится к [49], зависит от того, как называется функция, а не от того, как она определена. Если код выглядит следующим образом, может быть более очевидным, что функция не имеет неявной ссылки на объект:

function method() { console.log(this.data); } function Foo() { this.data = 42, document.body.onclick = this.method; } Foo.prototype.method = method;

, называемый , такой же, как указано выше: если доступно, используйте .bind, чтобы явно привязать this к определенному значению

document.body.onclick = this.method.bind(this);

или явно вызвать функцию как «метод» объекта, используя анонимную функцию в качестве обратного вызова / event и присвоить объект (this) другой переменной:

var self = this; document.body.onclick = function() { self.method(); };

или использовать функцию стрелки:

document.body.onclick = () => this.method();
1221
ответ дан NomadeNumerique 15 August 2018 в 12:43
поделиться

Мы не можем привязать это к setTimeout(), поскольку он всегда выполняется с глобальным объектом (Window), если вы хотите получить доступ к контексту this в функции обратного вызова, а затем с помощью bind() к функции обратного вызова, которую мы можем достичь как:

setTimeout(function(){ this.methodName(); }.bind(this), 2000);
11
ответ дан Aliaksandr Sushkevich 15 August 2018 в 12:43
поделиться

Проблема с «context»

Термин «контекст» иногда используется для ссылки на объект, на который это ссылается. Его использование неуместно, потому что оно не подходит семантически или технически с помощью ECMAScript.

ECMAScript это означает обстоятельства, окружающие что-то, что добавляет смысл, или некоторые предыдущие и последующие данные, которые дает дополнительный смысл. Термин «контекст» используется в ECMAScript для ссылки на this , который представляет собой все параметры, область действия и этот в рамках некоторого исполняемого кода.

В показано это :

Задайте значение ThisBinding тем же значением, что и ThisBinding для контекста выполнения вызова

], который четко указывает, что это часть контекста выполнения.

Контекст выполнения предоставляет информацию, которая добавляет смысл исполняемому коду. Он содержит гораздо больше информации, что только thisBinding.

Таким образом, значение этого не является «контекстом», это всего лишь одна часть контекста выполнения. Это, по сути, локальная переменная, которая может быть задана вызовом любого объекта и в строгом режиме для любого значения вообще.

20
ответ дан arcy 15 August 2018 в 12:43
поделиться

Все в «волшебном» синтаксисе вызова метода:

object.property();

Когда вы получаете свойство из объекта и вызываете его за один раз, объект будет контекстом для метода , Если вы вызываете тот же метод, но в отдельных шагах, контекст представляет собой глобальную область (окно):

var f = object.property; f();

Когда вы получаете ссылку на метод, он больше не привязан к объекту, это просто ссылка на простую функцию. То же самое происходит, когда вы получаете ссылку на использование в качестве обратного вызова:

this.saveNextLevelData(this.setAll);

Здесь вы привязываете контекст к функции:

this.saveNextLevelData(this.setAll.bind(this));

Если вы используете jQuery вы должны использовать метод $.proxy, а bind не поддерживается во всех браузерах:

this.saveNextLevelData($.proxy(this.setAll, this));
35
ответ дан Guffa 15 August 2018 в 12:43
поделиться

Во-первых, вам нужно иметь четкое представление о scope и поведении ключевого слова this в контексте scope.

scope

there are two types of scope in javascript. They are : 1) Global Scope 2) Function Scope

, глобальная область относится к объекту window.Variables, объявленные в глобальной области, доступны из любого места. С другой стороны, область функций находится внутри функции. varariable this ключевое слово в глобальной области относится к объекту window. this внутренняя функция также относится к объекту window.So this всегда будет обратитесь к окну, пока мы не найдем способ манипулировать scope , чтобы указать контекст по собственному выбору.

-------------------------------------------------------------------------------- - - - Global Scope - - ( globally "this" refers to window object) - - - - function outer_function(callback){ - - - - // outer function scope - - // inside outer function"this" keyword refers to window object - - - callback() // "this" inside callback also refers window object - - } - - - - function callback_function(){ - - - - // function to be passed as callback - - - - // here "THIS" refers to window object also - - - - } - - - - outer_function(callback_function) - - // invoke with callback - --------------------------------------------------------------------------------

this

Здесь у меня есть функция-конструктор, называемая Person. Он имеет свойство, называемое name, и четыре метода, называемые this , sayNameVersion2, sayNameVersion3, sayNameVersion4. Все четыре из них имеют одну конкретную задачу. Возьмите обратный вызов и вызовите его. Обратный вызов имеет определенную задачу, которая заключается в регистрации свойства имени экземпляра функции конструктора Person.

function Person(name){ this.name = name this.sayNameVersion1 = function(callback){ callback.bind(this)() } this.sayNameVersion2 = function(callback){ callback() } this.sayNameVersion3 = function(callback){ callback.call(this) } this.sayNameVersion4 = function(callback){ callback.apply(this) } } function niceCallback(){ // function to be used as callback var parentObject = this console.log(parentObject) }

Теперь давайте создадим экземпляр из конструктора человека и вызывать разные версии name (X относится к 1,2,3,4) методу с niceCallback, чтобы увидеть, как много способов мы можем манипулировать sayNameVersion2 внутри обратного вызова для обращения к экземпляру person.

var p1 = new Person('zami') // create an instance of Person constructor

bind:

Что нужно сделать, так это создать новую функцию с помощью niceCallback установлено на предоставленное значение.

sayNameVersion1 и sayNameVersion2 используют bind для управления this функции обратного вызова.

this.sayNameVersion1 = function(callback){ callback.bind(this)() } this.sayNameVersion2 = function(callback){ callback() }

сначала связать this с обратным вызовом внутри самого метода. И для второго обратного вызова передается связанный с ним объект.

p1.sayNameVersion1(niceCallback) // pass simply the callback and bind happens inside the sayNameVersion1 method p1.sayNameVersion2(niceCallback.bind(p1)) // uses bind before passing callback

bind:

Метод first argument метода person используется как sayNameVersion3 внутри функция, которая вызывается с помощью call

sayNameVersion3 использует first argument , чтобы манипулировать this, чтобы ссылаться на созданный нами объект person вместо объекта window. [ ! d44] this.sayNameVersion3 = function(callback){ callback.call(this) }

и он называется следующим:

p1.sayNameVersion3(niceCallback)

bind:

Как и this , первый аргумент call относится к объекту, который будет обозначен ключевым словом this.

sayNameVersion4 использует this , чтобы манипулировать this, чтобы ссылаться на объект person

this.sayNameVersion4 = function(callback){ callback.apply(this) }

, и он называется следующим. Просто передается обратный вызов,

p1.sayNameVersion4(niceCallback)
16
ответ дан mic4ael 15 August 2018 в 12:43
поделиться

Вот несколько способов доступа к родительскому контексту внутри дочернего контекста -

Вы можете использовать функцию bind(). Храните ссылку на контекст / внутри внутри другой переменной (см. Пример ниже). Используйте функции ES6 Arrow. Alter Code / function design / architecture - для этого вы должны иметь команду над шаблонами проектирования в javascript.

1. Используйте функцию bind()

function MyConstructor(data, transport) { this.data = data; transport.on('data', ( function () { alert(this.data); }).bind(this) ); } // Mock transport object var transport = { on: function(event, callback) { setTimeout(callback, 1000); } }; // called as var obj = new MyConstructor('foo', transport);

Если вы используете underscore.js - http://underscorejs.org/#bind

transport.on('data', _.bind(function () { alert(this.data); }, this));

2 Сохраните ссылку на контекст / этот внутри другой переменной

function MyConstructor(data, transport) { var self = this; this.data = data; transport.on('data', function() { alert(self.data); }); }

3 Функция стрелки

function MyConstructor(data, transport) { this.data = data; transport.on('data', () => { alert(this.data); }); }
144
ответ дан Mohan Dere 15 August 2018 в 12:43
поделиться

Отличные ответы выше. Я хочу только добавить, что внутри области вашей функции вы можете присвоить значение этой переменной переменной let self = this;, а затем внутри обратного вызова просто обратиться к данным типа self.data.

Ваш код :

function MyConstructor(data, transport) {
    this.data = data;

    let self = this;   //ADD THIS LINE

    transport.on('data', function () {
        alert(self.data);   //USE IT LIKE THIS
    });
}

// Mock transport object
var transport = {
    on: function(event, callback) {
        setTimeout(callback, 1000);
    }
};

// called as
var obj = new MyConstructor('foo', transport);
0
ответ дан oetoni 15 August 2018 в 12:43
поделиться
0
ответ дан Andrea Puddu 5 September 2018 в 12:03
поделиться
0
ответ дан Think-Twice 5 September 2018 в 12:03
поделиться
0
ответ дан skyboyer 27 October 2018 в 01:47
поделиться
Другие вопросы по тегам:

Похожие вопросы: