Этот пост в блоге предназначен для разработчиков, которые уже знают, как писать программное обеспечение, и хотят узнать о Javascript. Я не учу вас писать программы, потому что предполагаю, что вы можете программировать на другом языке. Я также предполагаю, что даже Javascript — ниндзя наслаждаются разговорами на темы, которые они могут знать или не знать.
- Синтаксический сахар
- Шаблоны JavaScript / Объекты в JavaScript
- Функции в JavaScript
- "это", указывая на это
- ООП (объектно-ориентированное программирование)
это ключевое слово
Это сбивает с толку меня, а также опытных разработчиков. К тому времени, когда мы закончим эту статью, это станет частью Javascript, о которой нам больше никогда не придется беспокоиться. Это может быть очень неприятно, когда вы пришли из C++, где указатель this непротиворечив во всем его использовании.
var car = {
"engine":"2L",
"seatCount":5,
"buildCar":function(){
return this.engine + " needs " + this.seatCount;
}
};
Если мы используем car.engine и car.seatCount, наш код становится неоднозначным. Учтите, что может быть другая глобальная переменная (о которой мы можем знать или не знать) с именем «автомобиль». Шаблоны проектирования JavaScript с годами стали более изощренными, соответственно увеличилось количество самоссылающихся областей видимости в обратных вызовах и замыканиях, которые являются довольно распространенным источником путаницы «это/то».
Если вы понимаете парадигму this в Javascript, вы ясно поймете ключевое слово this: this не присваивается значение до тех пор, пока объект не вызовет функцию, в которой ключевое слово this определено. Однако в вашей разработке бывают моменты, когда this не имеет значения вызывающего объекта. Давайте рассмотрим пример, где Game — это объект с функциями перезапуска. Логика перезапуска требует тайм-аута 0 миллисекунд, когда она вызывается.
Game.prototype.restart = function () {
this.clearLocalStorage();
this.timer = setTimeout(function() {
this.clearBoard(); // what is "this"?
}, 0);
};
Причина, по которой вы получаете указанную выше ошибку, заключается в том, что когда вы вызываете setTimeout(), вы фактически вызываете window.setTimeout(). Традиционное решение состоит в том, чтобы просто сохранить вашу ссылку на this в переменной, например, в self, которая затем может быть унаследована замыканием.
Game.prototype.restart = function () {
this.clearLocalStorage();
var self = this;// save reference to 'this'
this.timer = setTimeout(function(){
self.clearBoard();
}, 0);
};
Во-первых, знайте, что все функции в Javascript имеют свойства, как и объекты. И когда функция выполняется, она получает свойство this — переменную со значением объекта, который вызывает функцию, где this используется. Звучит запутанно, верно? Не беспокойтесь. Кроме того, в более новых браузерах вы можете использовать метод bind() для передачи правильной ссылки. Но это утомительно и чревато ошибками, если учесть, сколько кода вы напишете за свою карьеру разработчика.
Подать заявку и позвонить
Методы Apply и Call — это два наиболее часто используемых метода Function в JavaScript, и на то есть веская причина: они позволяют нам заимствовать функции и устанавливать значение this при вызове функции. Кроме того, функция применения, в частности, позволяет нам выполнять функцию с массивом параметров, так что каждый параметр передается в функцию отдельно при выполнении функции, давайте покажем пример:
var personObject = {
"firstName": "Michel",
"lastName": "Herszak",
}
var assembleName = function () {
console.log(this.firstName + " " + this.lastName);
}
// Do it the wrong way where this refers to the global object, hence, firstName and lastName is not defined
assembleName(); // output: undefined undefined
// now use call and you call the function sayName and bind the person object to it
assembleName().call(personObject); // output: Michel Herszak
Какой вызов вызывает функцию и связывает объект и значение this с его контекстом. Давайте сделаем нашу функцию сборки немного более гибкой и передадим аргументы.
var assembleName = function (arg1,arg2) {
console.log(this[arg1]);
console.log(this[arg2]);
}
assembleName().call(personObject,'lastName','firstName'); // output: Herszak Michel
В этом примере мы ожидаем, что функция сборки получит аргументы и передаст их в функцию вызова. Эта функция исключает ваши аргументы, как если бы вы передавали аргументы любой другой функции, за исключением того, что первый параметр является фактической ссылкой на this, как в контексте текущего объекта.
Методы Apply, Call и Bind используются для установки значения this при вызове метода, и они делают это немного по-разному, чтобы обеспечить прямое управление и гибкость в нашем коде JavaScript. Одно отличие, однако, заключается в том, что apply ожидает, что ваши параметры будут массивом аргументов, например.
assembleName().apply(personObject,['lastName','firstName']); // output: Herszak Michel
Таким образом, apply также переводит фактические значения из объекта, к которому вы привязываете указатель this. Другой фрагмент — это то, как вы могли бы вызвать применение:
var newFunc = function(){
assembleName().apply(personObject,arguments);
};
newFunc('firstName','lastName');
Что делает newFunc, он переводит все аргументы в массив и передает его в качестве второго параметра функции применения.
Так что помните:
- новый оператор создает контекст
- this присваивается экземпляру объекта, который вызывает случайный метод в определенный момент времени.
- Вы можете использовать привязку и привязать свой контекст
- Вы можете просто использовать такие переменные, как self, чтобы привязать это к определенной области.
- Подумайте о том, как включить приложения и вызовы в свою кодовую базу.
Электронная почта — [email protected]
Твиттер — @MHerszak (twitter.com/MHerszak)
Хотите узнать о том, как я работаю? Отлично, вы можете начать с обзора того, как я подхожу к проекту прямо здесь.
Дополнительную информацию можно найти здесь.
Первоначально опубликовано на www.browserstudios.com 21 декабря 2015 г.