Несмотря на то, что @ruakh дал хороший ответ, я добавлю несколько альтернатив для полноты:
Вы могли бы использовать даже var Omega = 'Ω'
в JavaScript, но только если ваш код JavaScript:
onclick="var Omega = 'Ω';
alert(Omega)"
или script
внутри документа XHTML (или XHTML + XML), который подается с типом содержимого XML. В этих случаях код будет первым (до того, как он будет передан интерпретатору JavaScript) проанализирован парсером HTML, чтобы распознать символьные ссылки, такие как Ω
. Ограничения делают это непрактичным подходом в большинстве случаев.
Вы также можете ввести символ Ω как таковой, как в var Omega = 'Ω'
, но тогда кодировка символов должна позволять это, кодирование должно быть должным образом объявлено, и вам нужно программное обеспечение, позволяющее вводить такие символы. Это чистое решение и вполне возможно, если вы используете кодировку UTF-8 для всего и готовы решать проблемы, созданные им. Исходный код будет читабельным, и, читая его, вы сразу увидите символ, а не код. С другой стороны, это может вызвать неожиданности, если другие люди начнут работать с вашим кодом.
Использование нотации \u
, как и в var Omega = '\u03A9'
, работает независимо от кодировки символов, и практически практически универсальный. Однако он может использоваться как таковой только до U + FFFF, то есть до \uffff
, но большинство персонажей, которые большинство людей когда-либо слышали, попадают в эту область. (Если вам нужны «более высокие» символы, вам нужно использовать суррогатные пары или один из двух подходов выше).
Вы также можете создать символ, используя метод String.fromCharCode()
, передавая в качестве параметра Номер Юникода, в десятичном формате, как в var Omega = String.fromCharCode(937)
, или в шестнадцатеричном виде, как в var Omega = String.fromCharCode(0x3A9)
. Это работает до U + FFFF. Этот подход можно использовать, даже если у вас есть номер Unicode в переменной.
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 .
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
, потому что его значение устанавливается автоматически, но на самом деле это не так.
Каждая функция имеет метод .bind
[docs] , который возвращает новую функцию с 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
's this
.
Примечание. При связывании контекста для jQuery вместо этого используйте jQuery.proxy
[docs] . Причина этого заключается в том, что вам не нужно сохранять ссылку на функцию при отмене обратного вызова события. jQuery обрабатывает это внутренне.
В ECMAScript 6 представлены функции стрелок , которые можно рассматривать как лямбда-функции. У них нет собственной привязки this
. Вместо этого this
просматривается в области видимости как обычная переменная. Это означает, что вам не нужно называть .bind
. Это не единственное особое поведение, которое у них есть. Дополнительную информацию см. В документации MDN.
function MyConstructor(data, transport) {
this.data = data;
transport.on('data', () => alert(this.data));
}
this
обратного вызова - часть 2 Некоторые функции / методы, которые принимают обратные вызовы, также принимают значение, к которому должен обращаться обратный вызов this
. Это в основном то же самое, что и привязывать его самостоятельно, но функция / метод делает это за вас. Array#map
[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);
или явно вызвать функцию как «метод» объекта, используя анонимную функцию в качестве обработчика обратного вызова / события и назначить object (
this
) к другой переменной:var self = this; document.body.onclick = function() { self.method(); };
или использовать функцию стрелки:
document.body.onclick = () => this.method();
Мы не можем привязать это к setTimeout()
, поскольку он всегда выполняется с глобальным объектом (Window), если вы хотите получить доступ к контексту this
в функции обратного вызова, а затем с помощью bind()
к функции обратного вызова, которую мы можем достичь как:
setTimeout(function(){
this.methodName();
}.bind(this), 2000);
Термин «контекст» иногда используется для ссылки на объект, на который ссылается this . Его использование неуместно, потому что оно не подходит ни семантически, ни технически с помощью ECMAScript в этом .
«Контекст» означает обстоятельства, окружающие что-то, что добавляет смысл , или некоторая предшествующая и следующая информация, которая дает дополнительный смысл. Термин «контекст» используется в ECMAScript для ссылки на контекст выполнения , который является всеми параметрами, областью действия и этой в рамках некоторого исполняемого кода.
Это показано в разделе 10.4.2 ECMA-262 :
Установите значение ThisBinding на то же значение, что и ThisBinding для контекста выполнения вызова
, в котором четко указано, что этот является частью контекста выполнения.
Контекст выполнения предоставляет информацию, которая добавляет смысл в код, который выполняется , Он содержит гораздо больше информации о том, что только thisBinding .
Таким образом, значение этого не является «контекстом», это всего лишь одна часть выполнения контекст. Это, по сути, локальная переменная, которая может быть задана вызовом любого объекта и в строгом режиме для любого значения вообще.
Это все в «волшебном» синтаксисе вызова метода:
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));
Во-первых, вам нужно иметь четкое представление о scope
и поведении ключевого слова this
в контексте scope
.
this
& amp; scope
:
there are two types of scope in javascript. They are :
1) Global Scope
2) Function Scope
вкратце, глобальная область относится к объекту window.Variables, объявленные в глобальной области, доступны из любого места. С другой стороны, область функций находится внутри функции .variable, объявленный внутри функции, не может быть доступен из внешнего мира в обычном режиме. this
ключевое слово в глобальной области относится к объекту window. Внутренняя функция this
также относится к объекту window.So this
всегда будет ссылаться на окно до тех пор, пока мы найдем способ манипулировать this
, чтобы указать контекст по собственному выбору.
--------------------------------------------------------------------------------
- -
- 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
, и четыре метода, называемые sayNameVersion1
, 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)
}
Теперь давайте создадим экземпляр из конструктора person и вызывать разные версии sayNameVersionX
(X относится к 1,2,3,4) методу с niceCallback
, чтобы увидеть, как много способов управления this
внутри обратного вызова ссылаться на person
.
var p1 = new Person('zami') // create an instance of Person constructor
Что нужно сделать, это создать новую функцию с ключевым словом this
, установленным на предоставленное значение.
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
first argument
в call
используется как функция this
внутри функции, которая вызывается с call
, прикрепленной к ней.
sayNameVersion3
использует call
для управления this
], чтобы ссылаться на созданный нами объект person, а не на объект окна.
this.sayNameVersion3 = function(callback){
callback.call(this)
}
и он называется следующим:
p1.sayNameVersion3(niceCallback)
Как и в call
, первый аргумент apply
относится к объекту, который будет обозначен ключевым словом this
.
sayNameVersion4
использует apply
для манипулирования this
для обращения к объекту человека
this.sayNameVersion4 = function(callback){
callback.apply(this)
}
, и он называется следующим. Просто передается обратный вызов,
p1.sayNameVersion4(niceCallback)
bind()
. 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));
function MyConstructor(data, transport) {
var self = this;
this.data = data;
transport.on('data', function() {
alert(self.data);
});
}
function MyConstructor(data, transport) {
this.data = data;
transport.on('data', () => {
alert(this.data);
});
}
self
иthat
для ссылки наthis
. Я так чувствую, потому чтоthis
- перегруженная переменная, используемая в разных контекстах; тогда какself
обычно соответствует локальному экземпляру, аthat
обычно относится к другому объекту. Я знаю, что вы не установили это правило, поскольку я видел, что он появился в ряде других мест, но именно поэтому я начал использовать_this
, но не уверен, как это себя чувствуют другие, - это была обычная практика. – vol7ron 12 September 2014 в 16:39Function.prototype.call ()
иFunction.prototype.apply ()
. В частности, сapply ()
у меня много пробега. Я менее склонен использоватьbind ()
, возможно, только по привычке, хотя я знаю (но не уверен), что могут быть небольшие накладные преимущества при использовании привязки по другим параметрам. – Nolo 15 November 2016 в 07:02() => this.clicked()
;) – alphanumeric0101 25 May 2018 в 20:36