- Оригинальный адрес:WTF is this - Understanding the this keyword, call, apply, and bind in JavaScript
- Оригинальный автор:Tyler McGinnis
- Перевод с:Программа перевода самородков
- Постоянная ссылка на эту статью:GitHub.com/rare earth/gold-no…
- Переводчик:CoolRice
- Корректор:Чжоу Цзявэй
Одна из самых неправильно понимаемых вещей в JavaScript — этоthis
ключевые слова. В этой статье вы узнаете о четырех правилах, разберетесьthis
К чему относится ключевое слово. Неявная привязка, явная привязка, новая привязка и привязка окна. Познакомившись с этими методами, вы также изучите некоторые другие запутанные части JavaScript, такие как.call
,.apply
,.bind
иnew
ключевые слова.
видео
- Ссылка на видео на ютубе:youtu.be/zE9iro4r918
текст
Глубокое понимание JavaScript вthis
Перед ключевыми словами необходимо сделать шаг назад и понять, почемуthis
Ключевые слова важны.this
Разные контексты разрешены при повторном использовании функций. другими словами,Ключевое слово this позволяет решить, какой объект должен быть в фокусе при вызове функции или метода.Все, что обсуждалось после этого, основано на этой идее. Мы хотим иметь возможность повторно использовать функции или методы в разных контекстах или в разных объектах.
Первое, на чем мы хотим сосредоточиться, это то, как судитьthis
Ссылки на ключевые слова. Первый и самый важный вопрос, который вы должны задать себе, пытаясь ответить на этот вопрос: «Где вызывается эта функция?".судитьthis
цитата или что-тоТолькоМетод заключается в использованииthis
Где вызывается этот метод ключевого слова.
Покажите это на примере, с которым вы уже хорошо знакомы, например, у нас естьgreet
метод, который принимает параметр имени и отображает окно предупреждения с приветственным сообщением.
function greet (name) {
alert(`Hello, my name is ${name}`)
}
если я спрошу тебяgreet
О чем конкретно вас предупредят и как вы отреагируете? Невозможно узнать ответ, просто дав определение функции. знатьname
что ты должен увидетьgreet
процесс вызова функции.
greet('Tyler')
судитьthis
То же самое относится и к ссылкам на ключевые слова, вы даже можете поставитьthis
Рассматривается как обычный параметр функции — он изменяется в зависимости от того, как вызывается функция.
Теперь мы знаем, что для того, чтобы судитьthis
Ссылка на функцию должна сначала посмотреть на определение функции.Когда мы на самом деле смотрим на определение функции, мы устанавливаем четыре правила, чтобы найти ссылку, они
- неявное связывание
- явная привязка
- новая привязка
- переплет окна
неявное связывание
Помните, что цель здесь — рассмотреть использованиеthis
определения функций ключевых слов и сужденияthis
указывает на. Первое и наиболее распространенное правило выполнения привязки называется隐式绑定
. В 80% случаев он скажет вамthis
К чему относится ключевое слово.
Предположим, у нас есть такой объект
const user = {
name: 'Tyler',
age: 27,
greet() {
alert(`Hello, my name is ${this.name}`)
}
}
Теперь, если бы вы позвонилиuser
на объектеgreet
метод, вы будете использовать запись через точку.
user.greet()
Это подводит нас к основному ключевому моменту правила неявной привязки. судитьthis
ссылки на ключевые слова,При вызове функции сначала посмотрите на левую сторону точки.. Если у вас есть «точка» для просмотра объекта с левой стороны, этот объектthis
цитаты.
В приведенном выше примереuser
На "левой стороне точки" означаетthis
Цитируетсяuser
объект. Так что простокаксуществуетgreet
Внутренний интерпретатор JavaScript метода помещаетthis
сталuser
.
greet() {
// alert(`Hello, my name is ${this.name}`)
alert(`Hello, my name is ${user.name}`) // Tyler
}
Давайте рассмотрим аналогичный, но немного более сложный пример. Теперь наш объект должен иметь не толькоname
,age
иgreet
атрибут, но и добавитьmother
свойство, и это свойство также имеетname
иgreet
Атрибуты.
const user = {
name: 'Tyler',
age: 27,
greet() {
alert(`Hello, my name is ${this.name}`)
},
mother: {
name: 'Stacey',
greet() {
alert(`Hello, my name is ${this.name}`)
}
}
}
Теперь возникает вопрос: о чем предупреждает каждый приведенный ниже вызов функции?
user.greet()
user.mother.greet()
всякий раз, когда судятthis
, нам всем нужно посмотреть на вызывающий процесс и подтвердить, что такое «левая сторона точки». Первый звонок,user
слева от точки означаетthis
будет цитироватьuser
. Во втором звонкеmother
слева от точки означаетthis
Цитироватьmother
.
user.greet() // Tyler
user.mother.greet() // Stacey
Как уже упоминалось, примерно в 80% случаев объект будет находиться «слева от точки». Вот почему судитьthis
«Посмотри налево от точки», когда тыкаешь пальцем — это первое, что ты делаешь. Но что делать, если точек нет? Это приводит нас к следующему правилу —
явная привязка
еслиgreet
функция неuser
Функция объекта, просто автономная функция.
function greet () {
alert(`Hello, my name is ${this.name}`)
}
const user = {
name: 'Tyler',
age: 27,
}
мы знаем, что для того, чтобы судитьthis
Сначала мы должны посмотреть, где вызывается эта функция. Теперь возникает вопрос, как мы можем сделатьgreet
При вызове методаthis
направлениеuser
объект? . Мы больше не можем просто использоватьuser.greet()
,так какuser
нисколькоgreet
метод. В JavaScript каждая функция содержит метод, который позволяет решить именно эту задачу, имя этого метода называетсяcall
.
«вызов» — это метод, который есть у каждой функции, который позволяет указать контекст для функции при ее вызове.
Имея это в виду, с помощью следующего кода вы можете вызватьgreet
время использоватьuser
Делай контекст.
greet.call(user)
Снова,call
— это атрибут, который есть у каждой функции, и первым переданным ему аргументом будет контекст, в котором вызывается функция. другими словами,this
будет указывать наcall
первый параметр .
Это основа правила 2 (явная привязка), потому что мы явно (используя.call
) указаноthis
цитаты.
Теперь давайтеgreet
Способ внесения небольшого изменения. Что, если мы хотим передать какие-то параметры? Не только их имена, но и языки, которые они знают. как ниже
function greet (lang1, lang2, lang3) {
alert(`Hello, my name is ${this.name} and I know ${lang1}, ${lang2}, and ${lang3}`)
}
Теперь для того, чтобы передать эти параметры для использования.call
Для вызова функции нужно передать ее по очереди после указания контекста (первый параметр).
function greet (lang1, lang2, lang3) {
alert(`Hello, my name is ${this.name} and I know ${lang1}, ${lang2}, and ${lang3}`)
}
const user = {
name: 'Tyler',
age: 27,
}
const languages = ['JavaScript', 'Ruby', 'Python']
greet.call(user, languages[0], languages[1], languages[2])
метод работает, он показывает, как передать параметры с помощью.call
функция вызова. Однако вы можете заметить, что вам придется проходить один за другимlanguages
элементы массива, что несколько раздражает. Было бы неплохо, если бы мы могли взять весь массив в качестве второго параметра и позволить JavaScript развернуть его для нас. Есть хорошие новости, это.apply
заниматься вещами..apply
и.call
По сути то же самое, но вместо того, чтобы передавать параметры один за другим, вы можете передавать параметры массивом и.apply
автоматически расширится для вас в функции.
затем используйте.apply
, наш код можно изменить на следующий, все остальное остается прежним.
const languages = ['JavaScript', 'Ruby', 'Python']
// greet.call(user, languages[0], languages[1], languages[2])
greet.apply(user, languages)
До сих пор мы узнали о.call
и.apply
Правило «Явная привязка», метод, вызываемый с этим правилом, позволяет указатьthis
Указатель внутри метода. Последняя часть об этом правиле.bind
..bind
и.call
Точно так же, за исключением того, что вместо немедленного вызова функции возвращается новая функция, которую можно вызвать позже. Итак, если мы посмотрим на код, который мы написали ранее, заменим.bind
, это выглядит так
function greet (lang1, lang2, lang3) {
alert(`Hello, my name is ${this.name} and I know ${lang1}, ${lang2}, and ${lang3}`)
}
const user = {
name: 'Tyler',
age: 27,
}
const languages = ['JavaScript', 'Ruby', 'Python']
const newFn = greet.bind(user, languages[0], languages[1], languages[2])
newFn() // alerts "Hello, my name is Tyler and I know JavaScript, Ruby, and Python"
новая привязка
Статья 3 Решениеthis
Цитируемое правилоnew
связывать. Если вы не знакомы с JavaScriptnew
ключевые слова, на самом деле, всякий раз, когда вы используетеnew
При вызове функции интерпретатор JavaScript создает новый объект под капотом и обрабатывает этот объект какthis
. Если вы используетеnew
вызвать функцию,this
будет естественным образом ссылаться на новые объекты, созданные интерпретатором.
function User (name, age) {
/*
JavaScript 会在底层创建一个新对象 `this`,它会代理不在 User 原型链上的属性。
如果一个函数用 new 关键字调用,this 就会指向解释器创建的新对象。
*/
this.name = name
this.age = age
}
const me = new User('Tyler', 27)
переплет окна
Если у нас есть следующий код
function sayAge () {
console.log(`My age is ${this.age}`)
}
const user = {
name: 'Tyler',
age: 27
}
Как уже упоминалось, если вы хотите использоватьuser
делать контекстные вызовыsayAge
,ты можешь использовать.call
,.apply
или.bind
. Но если мы не используем эти методы, а вызываем напрямую, как обычноsayAge
Что случится?
sayAge() // My age is undefined
Не удивительно, что вы получитеMy name is undefined
,так какthis.age
не определено. Вещи начали становиться волшебными. На самом деле это потому, что слева от точки ничего нет, и нам это не нужно..call
,.apply
,.bind
илиnew
ключевое слово, JavaScript по умолчанию будет использоватьthis
направлениеwindow
объект. Это означает, что если мыwindow
объект добавленage
свойство и позвоните сноваsayAge
метод,this.age
больше не будет неопределенным и станет объектом окнаage
стоимость имущества. Не верю? Давайте запустим этот код
window.age = 27
function sayAge () {
console.log(`My age is ${this.age}`)
}
Довольно удивительно, не так ли? Поэтому правило 4window 绑定
причина. Если ни одно из других правил не выполняется, JavaScript по умолчанию используетthis
направлениеwindow
объект.
Добавлено в ES5
严格模式
, JavaScript по умолчанию неthis
указывает на объект окна, но правильно поставитthis
остается неопределенным.
'use strict'
window.age = 27
function sayAge () {
console.log(`My age is ${this.age}`)
}
sayAge() // TypeError: Cannot read property 'age' of undefined
Итак, применяя все правила на практике, всякий раз, когда я вижу внутри функцииthis
ключевое слово, это шаги, которые я предпринимаю, чтобы судить о его цитировании.
- Посмотрите, где вызывается функция.
- Есть ли объект слева от точки? Если есть, то это ссылка на «это». Если нет, перейдите к шагу 3.
- Была ли функция вызвана с помощью «вызова», «применения» или «привязки»? Если это так, это явно относится к «этому». Если нет, перейдите к шагу 4.
- Была ли функция вызвана с «новым»? Если это так, то «это» относится к объекту, вновь созданному интерпретатором JavaScript. Если нет, перейдите к шагу 5.
- Вы находитесь в «строгом режиме»? Если это так, «это» не определено, если нет, перейдите к шагу 6.
- JavaScript странен, потому что «это» указывает на объект «окно».
Примечание: Многие друзья не упомянули в комментариях функции стрелок, поэтому переводчик написал специальную статью в качестве дополнения, если вам нужно знать, пожалуйста, переместитеТакже поговорите об этом, указывая на функцию стрелки и связанные с этим проблемы..
Если вы обнаружите ошибки в переводе или в других областях, требующих доработки, добро пожаловать наПрограмма перевода самородковВы также можете получить соответствующие бонусные баллы за доработку перевода и PR. начало статьиПостоянная ссылка на эту статьюЭто ссылка MarkDown этой статьи на GitHub.
Программа перевода самородковэто сообщество, которое переводит высококачественные технические статьи из Интернета сНаггетсДелитесь статьями на английском языке на . Охват контентаAndroid,iOS,внешний интерфейс,задняя часть,блокчейн,продукт,дизайн,искусственный интеллектЕсли вы хотите видеть более качественные переводы, пожалуйста, продолжайте обращать вниманиеПрограмма перевода самородков,официальный Вейбо,Знай колонку.