зачем использовать это
Чтобы ответить на этот вопрос, давайте посмотрим, не используем ли мыthisЧто пойдет не так. Попробуйте следующий код, если вы не используетеthisКак это должно быть написано:
function speak(){
var name = this.name
console.log(`Hello I am ${name}`)
}
var me = {
name: 'a',
speak: speak
}
var you = {
name: 'b',
speak: speak
}
me.speak() //Hello I am a
you.speak() //Hello I am b
thisРазличные объекты контекста могут использоваться в одной и той же среде выполнения. На самом деле он обеспечивает более элегантный способ неявной «передачи» ссылки на объект, что делает дизайн API более лаконичным и простым для повторного использования.
это кто
thisНи сама, ни область действия текущей функции. Мы можем проверить это с помощью кода.
- судить, так ли это
function fn(){
console.log(this.name)
}
fn.name = 'xxx'
fn() //undefined
- Определить, является ли это областью
function foo() {
var a = 2;
this.bar();
}
function bar() {
console.log( this.a );
}
foo(); //undefined
ТакthisКто это? Не обязательно,thisпривязан к среде выполнения, поэтому зависит от контекста выполнения функции.
При вызове функции создается активная запись (контекст выполнения). Эта запись будет содержать такую информацию, как место вызова функции (стек вызовов), способ вызова функции и передаваемые параметры. Здесь это тоже атрибут.
Как судить об этом указывает на
КонечноthisУказание — это определение контекста выполнения функции, то есть «кто её вызвал».Существует несколько способов судить:
Автономный вызов функции
function foo(){
console.log(this.a)
}
var a = 2
foo() // 2
Этот способ вызова напрямуюthisУказывает на глобальный объект или если он находится в браузереwindow
Контекст объекта (неявная привязка)
function foo() {
console.log( this.a );
}
var obj = {
a: 2,
foo: foo
};
obj.foo(); // 2
fooХотя он определен в глобальной области видимости, он вызывается черезobjупоминается в контексте, можно понять, что вfooв тот момент, когда это называетсяobjОбъект владеет. такthisнаправлениеobj.
Здесь есть две проблемы:
- цепной вызов
В случае связанных вызовов только последний уровень будет влиять на позицию вызова, например:
obj1.obj2.obj3.fn() //这里的fn中的this指向obj3
- потерянная цитата
function foo() {
console.log( this.a );
}
var obj = {
a: 2,
foo: foo
};
var bar = obj.foo; // 函数别名!
var a = "xxxxx"
bar(); // xxxxx
здесьbarфактически цитируетсяobj.fooадрес, этот адрес указывает на функцию, то естьbarВызов фактически соответствует правилу «независимого вызова функции». так что этоthisнетobj.
Функция обратного вызова на самом деле неявно потеряна
Измените код выше немного:
function foo() {
console.log( this.a );
}
var obj = {
a: 2,
foo: foo
};
var a = "xxxxx"
setTimeout( obj.foo ,100); // xxxxx
Мы видим, что хотя функция обратного вызова передается черезobjцитируется, ноthisни одинobj. На самом деле реализация встроенной функции setTimeout() аналогична следующему псевдокоду:
function setTimeout(fn, delay){
//等待delay毫秒
fn()
}
На самом деле этот код скрывает эту операциюfn=obj.foo, то же самое, что и в примере вышеbar=obj.fooТо же самое.
явная привязка
Явное связывание противоположно неявному связыванию, которое относится кcall,apply,bindявно изменитьthisнаправление.
Первым параметром этих трех методов являетсяthisпредмет, на который нужно указать.
Обратите внимание, что если вы передадите тип значения (строка, логическое значение, число) в первый параметр, значение будет преобразовано в объектную форму (вызов new String(..), new Boolean(..), new Number( ..) ).
из этих трех методовbindМетод особенный, он может задерживать выполнение метода, что позволяет писать более гибкий код. Его принцип также легко смоделировать:
function foo(something) {
console.log( this.a, something );
return this.a + something;
}
function bind(fn, obj) {
return function() {
return fn.apply( obj, arguments );
};
}
var obj = {
a:2
};
var bar = bind( foo, obj );
var b = bar( 3 ); // 2 3
console.log( b ); // 5
Примечание. Если первый параметр передан в значении null или undefined, это значение будет проигнорировано, что эквивалентно соблюдению правил вызова независимых функций.
новый переплет
в ДжnewВ отличие от традиционного механизма языка, ориентированного на классы, «конструктор» в Js фактически ничем не отличается от обычных функций.
На самом деле, когда мы используемnewПри вызове функции происходит следующее:
- Создать совершенно новый объект
- Этот новый объект будет связан с "прототипом"
- Этот новый объект будет связан с призванием этого
- Если функция не имеет возвращаемого значения типа объект, будет возвращен этот объект
Среди них третья ступень связанаthis, поэтому "конструктор" и прототип вthisвсегда указыватьnewиз примеров.
приоритет
Веса вышеупомянутых четырех правил суждения увеличиваются. Порядок суждения таков:
- функция
newот,thisуказать на экземпляр - Функция связана вызовом, применением, связыванием,
thisуказывает на первый параметр привязки - функция вызывается в некотором объекте контекста (неявно связанном),
thisуказать на объект контекста - ни один из вышеперечисленных,
thisуказывает на глобальный объект
Отличия в строгом режиме
Все вышеперечисленное установлено в нестрогом режиме, а в строгом режимеthisНаведение разное.
- Автономный вызов функции:
thisнаправлениеundefined - методы на объектах:
thisвсегда указывать на этот объект - другое без разницы
это в стрелочных функциях
Стрелочные функции не передаютсяfunctionключевое слово определено, и не используйте вышеуказанноеthisправила, но "наследуют" от охватывающей областиthisнаправление.
На самом деле, хотя стрелочной функции вместе нет, мы часто делаем вещи, которые имеют тот же эффект, что и стрелочные функции, например:
function foo() {
var self = this;
setTimeout( function(){
console.log( self );
}, 100 );
}
это в геттерах и сеттерах
в эс6getterилиsetterфункция будетthisПривязать к объекту, который задает или получает свойства.
function sum() {
return this.a + this.b + this.c;
}
var o = {
a: 1,
b: 2,
c: 3,
get average() {
return (this.a + this.b + this.c) / 3;
}
};
Object.defineProperty(o, 'sum', { get: sum, enumerable: true, configurable: true} );
console.log(o.average, o.sum); // logs 2, 6
использованная литература
MDN - this
«Вы не знаете JavaScript, том 1»