Что означает "this" в функциях стрелок в ES6?
В нескольких местах я читал, что ключевым отличием является то, что "this
лексически привязана к функциям стрелки". Это все хорошо и хорошо, но я на самом деле не знаю, что это значит.
Я знаю, что это означает, что он уникален в пределах фигурных скобок, определяющих тело функции, но я не мог сказать вам результат следующего кода, потому что я понятия не имею, к чему относится this
, если только он ссылаясь на тучную функцию стрелки.... что не кажется полезным.
var testFunction = () => { console.log(this) };
testFunction();
Ответы
Ответ 1
Функции стрелок захватывают значение this
окружающего контекста
function Person(){
this.age = 0;
setInterval(() => {
this.age++; // |this| properly refers to the person object
}, 1000);
}
var p = new Person();
Итак, чтобы прямо ответить на ваш вопрос, this
внутри вашей функции стрелки будет иметь то же значение, что и раньше, прежде чем назначить функцию стрелки.
Ответ 2
Чтобы представить большую картину, я собираюсь объяснить как динамическую, так и лексическую привязку.
Связывание динамического имени
this
относится к объекту, на который вызывается метод. Это регулярно читаемое предложение на SO. Но это все еще только фраза, довольно абстрактная. Есть ли соответствующий шаблон кода для этого предложения?
Да, есть:
const o = {
m() { console.log(this) }
}
// the important patterns: applying methods
o.m(); // logs o
o["m"](); // logs o
m
- это метод, потому что он полагается на this
. o.m()
или o["m"]()
означает m
применяется к o
. Эти шаблоны - это перевод Javascript на нашу знаменитую фразу.
Существует еще один важный шаблон кода, на который вы должны обратить внимание:
"use strict";
const o = {
m() { console.log(this) }
}
// m is passed to f as a callback
function f(m) { m() }
// another important pattern: passing methods
f(o.m); // logs undefined
f(o["m"]); // logs undefined
Он очень похож на предыдущий шаблон, только скобки отсутствуют. Но последствия значительны: когда вы передаете m
функции f
, вы вытаскиваете m
своего объекта/контекста o
. Теперь он выкорчеван и this
ничего не означает (предполагается строгий режим).
Лексическая (или статическая) привязка имени
Функции стрелок не имеют привязки this
/super
/arguments
. Они наследуют их от родительской лексической области:
const toString = Object.prototype.toString;
const o = {
foo: () => console.log("window", toString.call(this)),
bar() {
const baz = () => console.log("o", toString.call(this));
baz();
}
}
o.foo() // logs window [object Window]
o.bar() // logs o [object Object]
Ответ 3
Надеюсь, что это показание кода может дать вам более четкую идею. В принципе, 'this' в функции стрелок есть текущая версия контекста 'this'. Смотрите код:
// 'this' in normal function & arrow function
var this1 = {
number: 123,
logFunction: function () { console.log(this); },
logArrow: () => console.log(this)
};
this1.logFunction(); // Object { number: 123}
this1.logArrow(); // Window
Ответ 4
Функция стрелки this
указывает на окружающий родительский элемент в Es6, означает, что он не имеет области видимости, как анонимные функции в ES5...
Это очень полезный способ избежать присвоения var self этому, который широко используется в ES5...
Посмотрите пример ниже, назначив функцию внутри объекта:
var checkThis = {
normalFunction: function () { console.log(this); },
arrowFunction: () => console.log(this)
};
checkThis.normalFunction(); //Object {}
checkThis.arrowFunction(); //Window {external: Object, chrome: Object, document: document, tmpDebug: "", j: 0…}
Ответ 5
Вы можете попытаться понять это, следуя ниже.
// whatever here it is, function or fat arrow or literally object declare
// in short, a pair of curly braces should be appeared here, eg:
function f() {
// the 'this' here is the 'this' in fat arrow function below, they are
// bind together right here
// if 'this' is meaningful here, eg. this === awesomeObject is true
console.log(this) // [object awesomeObject]
let a = (...param) => {
// 'this is meaningful here too.
console.log(this) // [object awesomeObject]
}
поэтому 'this' в функции стрелки жира не привязана, значит вы не можете сделать что-либо привязанным к 'this' здесь,.apply не будет,.call не будет,.bind не будет. 'this' в функции жирной стрелки привязывается при записи текста кода в текстовом редакторе. 'this' в функции толстой стрелки здесь буквально значима. Что ваш код писать здесь, в текстовом редакторе, то, что ваше приложение работает там в repl. Что 'this' связанное с оберткой жира никогда не изменится, если вы не измените его в текстовом редакторе.
Извините за мой пул English...
Ответ 6
В другом примере, если вы нажмете кнопку возраста ниже
<script>
var person = {
firstName: 'John',
surname: 'Jones',
dob: new Date('1990-01-01'),
isMarried: false,
age: function() {
return new Date().getFullYear() - this.dob.getFullYear();
}
};
var person2 = {
firstName: 'John',
surname: 'Jones',
dob: new Date('1990-01-01'),
isMarried: false,
age: () => {
return new Date().getFullYear() - this.dob.getFullYear();
}
};
</script>
<input type=button onClick="alert(person2.age());" value="Age">
это вызовет исключение, подобное этому
× Ошибка JavaScript: Uncaught TypeError: Невозможно прочитать свойство 'getFullYear' с неопределенным значением в строке 18
Но если вы измените person2 эту строку
return new Date().getFullYear() - this.dob.getFullYear();
в
return new Date().getFullYear() - person2.dob.getFullYear();
это будет работать, потому что эта область изменилась в person2