когда я начну учитьсяJavaScript
Когда потребовалось некоторое время, чтобы понятьJavaScript
серединаthis
ключевые слова и может быстро определитьthis
Объект, на который указывает ключевое слово. Я нашел пониманиеthis
Самое сложное в ключевых словах то, что вы часто забываете, что когда читали или смотрели какие-тоJavaScript
Различные кейс-ситуации объясняются в курсе или ресурсе. существуетES6
Все стало еще более запутанным после того, как стрелочные функции были введены вthis
Лечить ключевые слова по-разному. Я хотел написать эту статью, чтобы указать то, что я узнал и пытаюсь сделать это таким образом, чтобы кто-нибудь помогли кому-либоJavaScript
и непонятноthis
Ключевое слово, как его интерпретируют люди.
Как вы, возможно, знаете, выполните любоеJavaScript
окружение строки (илиscope
) называется "контекст выполнения".Javascript
Время выполненияСтек этих контекстов выполнения поддерживается, и в настоящее время выполняются контексты выполнения, находящиеся поверх этого стека.this
Объект, на который ссылается переменная, изменяется каждый раз, когда изменяется контекст выполнения.
По умолчанию контекст выполнения является глобальным, что означает, что если код выполняется как часть простого вызова функции,this
переменная будет ссылаться наглобальный объект. В случае браузера глобальный объектwindow
объект. Например, вNode.js
В среде это значение является специальным объектомglobal
.
Например, попробуйте следующий простой вызов функции:
function foo () {
console.log("Simple function call");
console.log(this === window);
}
foo();
передачаfoo()
, чтобы получить вывод:
“Simple function call”
true
доказать здесьthis
указывает на глобальный объект, в данном случаеwindow
.
Обратите внимание, что еслистрогий режимВниз,this
Значение будетundefined
, так как в строгом режиме глобальный объект указывает наundefined
вместоwindow
.
Попробуйте следующий пример:
function foo () {
'use strict';
console.log("Simple function call");
console.log(this === window);
}
foo();
выход:
“Simple function call”
false
Давай еще раз попробуемКонструкториз:
function Person(first_name, last_name) {
this.first_name = first_name;
this.last_name = last_name;
this.displayName = function() {
console.log(`Name: ${this.first_name} ${this.last_name}`);
};
}
СоздайтеPerson
Пример:
let john = new Person('John', 'Reid');
john.displayName();
получил ответ:
"Name: John Reid"
Что тут происходит? когда мы звонимnew Person
,JavaScript
Будет вPerson
Создайте новый объект внутри функции и сохраните его какthis
. тогда,first_name
, last_name
а такжеdisplayName
свойства будут добавлены во вновь созданныйthis
на объекте. следующим образом:
вы заметите вPerson
изконтекст выполнениясоздан вthis
объект, этот объект имеетfirst_name
, last_name
а такжеdisplayName
Атрибуты. Надеюсь, вы можете понять в соответствии с изображением вышеthis
Как создаются объекты и добавляются свойства.
Мы рассмотрели два связанныхthis
Обычный случай привязки Мне пришлось придумать этот более запутанный пример, следующую функцию:
function simpleFunction () {
console.log("Simple function call")
console.log(this === window);
}
Мы уже знаем, что если вызвать простую функцию, как показано ниже,this
Ключевое слово будет указывать на глобальный объект, в этом случаеwindow
объект.
simpleFunction()
Таким образом, результирующий вывод:
“Simple function call”
true
Создайте простойuser
Объект:
let user = {
count: 10,
simpleFunction: simpleFunction,
anotherFunction: function() {
console.log(this === window);
}
}
Теперь у нас естьsimpleFunction
атрибут указывает наsimpleFunction
функцию, также добавьте еще один вызов свойстваanotherFunction
функциональный метод.
если звонишьuser.simpleFunction()
, чтобы получить вывод:
“Simple function call”
false
Почему это так? потому чтоsimpleFunction()
сейчасuser
свойство объекта, поэтомуthis
указать на этоuser
объект вместо глобального объекта.
когда мы звонимuser.anotherFunction
, с тем же результатом.this
ключевое слово указывает наuser
объект. так,console.log(this === window);
должен вернутьсяfalse
:
false
Опять же, что возвращает следующая операция?
let myFunction = user.anotherFunction;
myFunction();
Теперь получите результат:
true
Так что случилось снова? В этом примере мы инициируем нормальный вызов функции. Как и прежде, если метод выполняется в нормальной функции, тоthis
Ключевое слово будет указывать на глобальный объект (в данном случае этоwindow
объект). такconsole.log(this === window);
выходtrue
.
Давайте посмотрим на другой пример:
var john = {
name: 'john',
yearOfBirth: 1990,
calculateAge: function() {
console.log(this);
console.log(2016 - this.yearOfBirth);
function innerFunction() {
console.log(this);
}
innerFunction();
}
}
передачаjohn.calculateAge()
Что случится?
{name: "john", yearOfBirth: 1990, calculateAge: ƒ}
26
Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}
calculateAge
внутри функции,this
направлениеjohn
объект, однако, вinnerFunction
внутри функции,this
указывает на глобальный объект (в данном случаеwindow
), некоторые считают, что этоJS
ошибка, но правила говорят нам, что всякий раз, когда вызывается обычная функция,this
будет указывать на глобальный объект.
...
чему я научилсяJavaScript
Функция также является особым видом объекта, каждая функция имеетcall
, apply
, bind
метод. Эти методы используются для установки контекста выполнения функции.this
стоимость.
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
this.displayName = function() {
console.log(`Name: ${this.firstName} ${this.lastName}`);
}
}
Создайте два экземпляра:
let person = new Person("John", "Reed");
let person2 = new Person("Paul", "Adams");
передача:
person.displayName();
person2.displayName();
результат:
Name: John Reed
Name: Paul Adams
вызов:
person.displayName.call(person2);
То, что указано выше, установленоthis
ценностьperson2
объект. следовательно,
Name: Paul Adams
применять:
person.displayName.apply([person2]);
получать:
Name: Paul Adams
call
,apply
Единственная разница заключается в том, как передаются параметры,apply
Вы должны передать массив,call
параметры должны передаваться отдельно.
мы используемbind
сделать то же самое,bind
Возвращает новый метод, в которомthis
Указывает на первый переданный параметр.
let person2Display = person.displayName.bind(person2);
передачаperson2Display
,получатьName: Paul Adams
результат.
...
стрелочная функция
В ES6 появился новый способ определения функций. следующим образом:
let displayName = (firstName, lastName) => {
console.log(Name: ${firstName} ${lastName});
};
В отличие от обычных функций, стрелочные функции не имеют собственныхthis
ключевые слова. Они просто используютthis
ключевые слова. у них естьthis
Лексические переменные.
ES5:
var box = {
color: 'green', // 1
position: 1, // 2
clickMe: function() { // 3
document.querySelector('body').addEventListener('click', function() {
var str = 'This is box number ' + this.position + ' and it is ' + this.color; // 4
alert(str);
});
}
}
Если вы позвоните:
box.clickMe()
Содержимое всплывающего окна будетThis is box number undefined and it is undefined'
.
Давайте проанализируем, что происходит шаг за шагом. существует//1
а также//2
Ряд,this
ключевые слова могут быть доступныcolor
а такжеposition
Атрибут, потому что он указывает наbox
объект. существуетclickMe
внутри метода,this
ключевые слова могут быть доступныcolor
а такжеposition
свойство, потому что оно также указывает наbox
объект. но,clickMe
МетодquerySelector
Метод определяет функцию обратного вызова, а затем эта функция обратного вызова вызывается в виде обычной функции, поэтомуthis
указывать на глобальный объект вместоbox
объект. Конечно, глобальный объект не определенcolor
а такжеposition
свойства, поэтому мы получаемundefined
стоимость.
Мы можем исправить это с помощью ES5:
var box = {
color: 'green',
position: 1,
clickMe: function() {
var self = this;
document.querySelector('body').addEventListener('click', function() {
var str = 'This is box number ' + self.position + ' and it is ' + self.color;
alert(str);
});
}
}
Добавить кvar self = this
, который создает указатель наbox
объектthis
Рабочая область функции закрытия ключевого слова. Нам просто нужно использовать внутри функции обратного вызоваself
Переменная.
передача:
box.clickMe();
всплывающее содержимоеThis is box number 1 and it is green
.
Как использовать функцию стрелки для достижения вышеуказанного эффекта? Мы заменим функцию обратного вызова функции клика функцией стрелки.
var box = {
color: 'green',
position: 1,
clickMe: function() {
document.querySelector('body').addEventListener('click', () => {
var str = 'This is box number ' + this.position + ' and it is ' + this.color;
alert(str);
});
}
}
Магия стрелочных функций заключается в том, что они разделяютthis
Лексические ключевые слова. Итак, в этом примере внешняя функцияthis
Совместно со стрелочной функцией внешняя функцияthis
ключевое слово указывает наbox
объект, следовательно,color
а такжеposition
свойства будут правильнымиgreen
а также1
стоимость.
Еще один:
var box = {
color: 'green',
position: 1,
clickMe: () => {
document.querySelector('body').addEventListener('click', () => {
var str = 'This is box number ' + this.position + ' and it is ' + this.color;
alert(str);
});
}
}
ой! Теперь снова всплывает‘This is box number undefined and it is undefined’.
. Почему?
click
закрытие функции слушателя событийthis
Ключевое слово делится по пакету, который опускает егоthis
ключевые слова. В этом случае он обернут стрелочной функциейclickMe
,clickMe
стрелочная функцияthis
Ключевое слово указывает на глобальный объект, которым в данном случае являетсяwindow
объект. такthis.color
а такжеthis.position
будетundefined
потому чтоwindow
объект неposition
а такжеcolor
Атрибуты.
Я подумал, что покажу вам еще один, который поможет во многих случаях.map
функцию, мы определяемPerson
Метод конструктора выглядит следующим образом:
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
this.displayName = function() {
console.log(`Name: ${this.firstName} ${this.lastName}`);
}
}
Person
добавлено в прототипmyFriends
метод:
Person.prototype.myFriends = function(friends) {
var arr = friends.map(function(friend) {
return this.firstName + ' is friends with ' + friend;
});
console.log(arr);
}
Создайте экземпляр:
let john = new Person("John", "Watson");
передачаjohn.myFriends(["Emma", "Tom"])
,результат:
["undefined is friends with Emma", "undefined is friends with Tom"]
Этот пример очень похож на предыдущий пример.myFriends
Функцияthis
关键字指向回调对象。 но,map
Внутри функции закрытия находится обычный вызов функции. такmap
Внутри функции закрытияthis
указывает на глобальный объект, в данном случаеwindow
объект, поэтомуthis.firstName
неопределенный. Теперь попробуем исправить эту ситуацию.
- существует
myFriends
Указывается в теле функцииthis
для других переменных, таких какself
,так чтоmap
Замыкания в функции используют его.
Person.prototype.myFriends = function(friends) {
// 'this' keyword maps to the calling object
var self = this;
var arr = friends.map(function(friend) {
// 'this' keyword maps to the global object
// here, 'this.firstName' is undefined.
return self.firstName + ' is friends with ' + friend;
});
console.log(arr);
}
-
map
Использование функции закрытияbind
.
Person.prototype.myFriends = function(friends) {
// 'this' keyword maps to the calling object
var arr = friends.map(function(friend) {
// 'this' keyword maps to the global object
// here, 'this.firstName' is undefined.
return this.firstName + ' is friends with ' + friend;
}.bind(this));
console.log(arr);
}
передачаbind
вернетmap
копия функции обратного вызова,this
Ключевые слова сопоставляются с внешнимиthis
ключевое слово, то есть позвонитьmyFriends
метод,this
указывает на этот объект.
- Создайте
map
Функция обратного вызова — это стрелочная функция.
Person.prototype.myFriends = function(friends) {
var arr = friends.map(friend => `${this.firstName} is friends with ${friend}`);
console.log(arr);
}
Теперь внутри стрелочной функцииthis
Ключевое слово будет разделять лексическую область, которая не обертывала его, то есть экземплярmyFriends
.
Все приведенные выше решения выведут результат:
["John is friends with Emma", "John is friends with Tom"]
...
На данный момент я надеюсь, что мне удалось сделатьthis
Концепция ключевого слова немного более доступна для вас. В этой статье я расскажу о некоторых типичных ситуациях, с которыми сталкиваюсь, и о том, как с ними справляться, но, конечно, по мере того, как вы создаете больше проектов, вы будете сталкиваться с большим количеством ситуаций. Я надеюсь, что мое объяснение поможет вам приблизитьсяthis
Сохраняйте прочную основу при связывании тем с ключевыми словами. Если у вас есть какие-либо вопросы, предложения или улучшения, я всегда рад узнать больше и обменяться знаниями со всеми известными разработчиками. Не стесняйтесь написать отзыв, или напишите мне записку!