8.0 KiB
		
	
	
	
	
	
	
	
			
		
		
	
	title, localeTitle
| title | localeTitle | 
|---|---|
| this reference | эта ссылка | 
this ссылка
В JavaScript каждая функция имеет this ссылку, автоматически создаваемую при ее объявлении. Эта ссылка очень похожа на this ссылку на других языках на основе классов, таких как Java или C # (JavaScript - это язык, основанный на прототипе, и не понятие «класс»): он указывает, какой объект вызывает функцию (этот объект иногда называемый контекстом ). Однако в JavaScript this ссылка внутри функций может быть привязана к различным объектам в зависимости от того, где вызывается функция . Вот 5 основных правил для this привязки в JavaScript:
Правило 1
Когда функция вызывается в глобальной области, this ссылка по умолчанию привязана к глобальному объекту ( window в браузере или global в Node.js). Например:
function foo() { 
  this.a = 2; 
 } 
 
 foo(); 
 console.log(a); // 2 
Примечание. Если вы объявляете функцию foo() выше в строгом режиме, вы вызываете эту функцию в глобальной области, this будет undefined и присваивание this.a = 2 будет Uncaught TypeError исключение this.a = 2 .
Правило 2
Рассмотрим ниже пример:
function foo() { 
  this.a = 2; 
 } 
 
 var obj = { 
  foo: foo 
 }; 
 
 obj.foo(); 
 console.log(obj.a); // 2 
Очевидно, что в приведенном выше фрагменте функция foo() вызывается с контекстом, является объектом obj и this ссылка теперь привязана к obj . Поэтому, когда функция вызывается с объектом контекста, this ссылка будет привязана к этому объекту.
Правило 3
.call , .apply и .bind могут быть использованы на сайте вызова, чтобы явно привязать this . Использование .bind(this) - это то, что вы можете увидеть в довольно многих компонентах React.
var foo = function() { 
  console.log(this.bar) 
 } 
 
 foo.call({ bar: 1 }) // 1 
Вот краткий пример того , как каждый из них используется , чтобы связать this :
- .call():- fn.call(thisObj, fnParam1, fnParam2)
- .apply():- fn.apply(thisObj, [fnParam1, fnParam2])
- .bind():- const newFn = fn.bind(thisObj, fnParam1, fnParam2)
Правило 4
function Point2D(x, y) { 
  this.x = x; 
  this.y = y; 
 } 
 
 var p1 = new Point2D(1, 2); 
 console.log(p1.x); // 1 
 console.log(p1.y); // 2 
То, что вы должны заметить, это функция Point2D new ключевым словом, и this ссылка привязана к объекту p1 . Поэтому, когда функция вызывается с new ключевым словом, она создаст новый объект, и this ссылка будет привязана к этому объекту.
Примечание. Когда вы вызываете функцию с new ключевым словом, мы также называем ее конструкторной функцией .
Правило 5
JavaScript определяет значение this во время выполнения, исходя из текущего контекста. Таким образом, this может иногда указывать на то, что вы ожидаете.
Рассмотрим этот пример класса Cat с методом под названием makeSound() , следуя шаблону в правиле 4 (выше) с помощью функции-конструктора и new ключевого слова.
var Cat = function(name, sound) { 
    this.name = name; 
    this.sound = sound; 
    this.makeSound = function() { 
        console.log( this.name + ' says: ' + this.sound ); 
    }; 
 } 
 var kitty = new Cat('Fat Daddy', 'Mrrooowww'); 
 kitty.makeSound(); // Fat Daddy says: Mrrooowww 
Теперь давайте попробуем дать кошке способ annoy() людей, повторяя его звук 100 раз, каждые полсекунды.
var Cat = function(name, sound) { 
    this.name = name; 
    this.sound = sound; 
    this.makeSound = function() { 
        console.log( this.name + ' says: ' + this.sound ); 
    }; 
    this.annoy = function() { 
        var count = 0, max = 100; 
        var t = setInterval(function() { 
            this.makeSound(); // <-- this line fails with `this.makeSound is not a function` 
            count++; 
            if (count === max) { 
                clearTimeout(t); 
            } 
        }, 500); 
    }; 
 } 
 var kitty = new Cat('Fat Daddy', 'Mrrooowww'); 
 kitty.annoy(); 
Это не работает, потому что внутри обратного вызова setInterval мы создали новый контекст с глобальной областью, поэтому this больше не указывает на наш экземпляр киски. В веб - браузере, this будет вместо этого указывать на объект Window, который не имеет makeSound() метод.
Несколько способов заставить его работать:
- Перед созданием нового контекста, присвоить thisзначение локальной переменной с именемme, илиself, или что вы хотите назвать его, и использовать эту переменную внутри функции обратного вызова.
var Cat = function(name, sound) { 
    this.name = name; 
    this.sound = sound; 
    this.makeSound = function() { 
        console.log( this.name + ' says: ' + this.sound ); 
    }; 
    this.annoy = function() { 
        var count = 0, max = 100; 
        var self = this; 
        var t = setInterval(function() { 
            self.makeSound(); 
            count++; 
            if (count === max) { 
                clearTimeout(t); 
            } 
        }, 500); 
    }; 
 } 
 var kitty = new Cat('Fat Daddy', 'Mrrooowww'); 
 kitty.annoy(); 
- С ES6 вы можете не назначать thisлокальную переменную с помощью функции стрелки, которая связываетthisс контекстом окружающего кода, где она определена.
var Cat = function(name, sound) { 
    this.name = name; 
    this.sound = sound; 
    this.makeSound = function() { 
        console.log( this.name + ' says: ' + this.sound ); 
    }; 
    this.annoy = function() { 
        var count = 0, max = 100; 
        var t = setInterval(() => { 
            this.makeSound(); 
            count++; 
            if (count === max) { 
                clearTimeout(t); 
            } 
        }, 500); 
    }; 
 } 
 var kitty = new Cat('Fat Daddy', 'Mrrooowww'); 
 kitty.annoy();