Исследование описания стрелочной функции в книге Ruan Yifeng «Introduction to ES6».

JavaScript

предисловие

Вчера я разместил статью в паблике:

Оригинальная ссылка:Не стоит недооценивать себя, но этот вопрос действительно сложный

В некоторых группах было обсуждение, одно из которых касалось указателя this стрелочных функций. Для опровержения используется содержание статьи Ruan Yifeng «Introduction to ES6».

В целях конфиденциальности ник WeChat заблокирован:

ryf_group
ryf_group

Приведенный выше снимок экрана взят из «Введение в ECMAScript 6» Руана Ифэна:

this
this

Давайте посмотрим, как выглядит this функции стрелки и как понять содержание текста!

Катастрофа, вызванная проблемой

thisthis2

Сначала друг в группе закинул этот вопрос, почему два выхода разные.

Один - пустой человек, а другой - ценный человек?

Итак, давайте сначала проанализируем, в чем причина.

getval для обычных функций

let pp = new person("251");

Здесь создается экземпляр человека pp. Затем выполните pp.getval().

pp вызывает getval, что соответствует логике [кто звонит, указывает на], упомянутой в предыдущей статье, поэтому this из getval указывает на экземпляр pp и выводит содержимое экземпляра pp.

Этот выглядит так, как будто ни у кого нет никаких сомнений, и все в порядке.

getval для стрелочных функций

Аналогично, пусть pp = new person("251"); здесь создается экземпляр pp, а затем выполняется pp.getval().

Итак, на кого здесь указывает эта стрелочная функция?

Справочная статьяНе стоит недооценивать себя, но этот вопрос действительно сложный

this стрелочной функции: на кого бы ни указывал родитель, на кого указывает текущая стрелочная функция.

Здесь возникает вопрос, кто здесь является родителем стрелочной функции getval?

С точки зрения лексической области видимости вы можете видеть, что родителем getval является объект o, возвращаемый функцией person, но объект o не является областью действия функции и не имеет контекста this.Конечно, функция getval не может указывать на объект o. контекст объекта o.

По правилам, продолжаем искать это, вот мы и нашли функцию человека!

Вы закончили, this из getval указывает на this из функции человека, поэтому this из getval точно такое же, как this из функции человека. (На самом деле this стрелочной функции — это обычная переменная, указывающая на this родителя)

Итак, вопрос в том, на кого указывает функция this of person?

Мы добавляем некоторый журнал для улучшения понимания, код выглядит следующим образом:

var flag=996;
function person(fg){
    let o = new Object();
    o.flag = fg;
    o.getval=()=>{
        console.log(this);
    }
    this.a = 1;
    console.log("^^^^^^");
    console.log(this);
    console.log("^^^^^^");
    return o;
}
var pp = new person("251")
pp.getval();
console.log("&&&&&&&");
console.log(pp);
console.log("&&&&&&&");

// 输出结果如下:
^^^^^^
person {a: 1}
^^^^^^
person {a: 1}
&&&&&&&
{flag: "251", getval: ƒ}
&&&&&&&

Здесь функция getval является стрелочной функцией, мы знаем, что она всегда согласуется с this родительского человека, здесь контекст this человека устанавливает this.a = 1, поэтому печатается {a:1}.

И объект, возвращаемый в функции человека, здесь, когда выполняется новый оператор, используется объект o, возвращаемый человеком.

Итак, мы видим вывод экземпляра pp, который полностью выводит содержимое возвращаемого объекта функции person: {flag: "251", getval: ƒ}.

Здесь у нас возникает вопрос: в чем разница между this of person и this of pp instance?

Ключевым моментом здесь является: новый оператор

Поскольку функция person возвращает объект (кроме null), возвращаемое значение объекта person используется в new, а контекст this of person не возвращается экземпляру pp.

Здесь, если функция человека возвращает [число, строку, логическое значение и т. д.], то при новом возвращаемое значение будет проигнорировано, а контекст this функции человека будет возвращен объекту экземпляра по умолчанию.

Вот почему вывод экземпляра pp здесь не содержит this.a, определенного внутри функции person.

this функции стрелки указывает на this человека, который выводит this.a=1, но не содержит объект o, возвращаемый функцией person.

Резюме: this стрелочной функции здесь всегда указывает на this родителя, а не на экземпляр pp. Фактически, this стрелочной функции похоже на обычную переменную, которая связана с this родителя. функция.

пример:

var flag=996;
function person(fg){
    let o = new Object();
    o.flag = fg;
    o.getval=()=>{
        console.log(this);
    }
    this.a = 1;
    return true;
}
var pp = new person("251");
console.log(pp.a);// 1

Здесь, в новом человеке, возвращаемое значение функции человека не является объектом, поэтому оно напрямую игнорируется.

Экземпляр pp получает this объекта person.

стрелочная функция

Два момента:

  • В стрелочных функциях вызов и применение игнорируют этот параметр. (описание МДН)

На самом деле это «внешний вид», потому что this функции стрелки указывает на this родителя, и поскольку сама функция стрелки не имеет this, она не может изменить свое собственное this, поэтому оно «игнорируется». .

  • this стрелочной функции всегда следует за this родителя.

Это стрелочной функции состоит в том, чтобы искать этот уровень из текущей стрелочной функции.Если он будет найден, он будет указан как собственный this, а если нет, он продолжит поиск. Родительское this является изменчивым, поэтому стрелочная функция this также может следовать за изменением родителя.

Почему это всегда следует за родительским this ? Поскольку на самом деле this стрелочной функции похоже на обычную переменную, содержимое переменной — это this родительской функции, присвоение переменной.

Следовательно, невозможно изменить this стрелочной функции «саму себя».

Но вы можете изменить this родителя, чтобы изменить this дочерней стрелочной функции.

есть каштан

function outer(){
    var inner = function(){
        var obj = {};
        obj.getVal=()=>{
            console.log("*******");
            console.log(this);
            console.log("*******");
        }
        return obj;
    };
    return inner; 
}
outer()().getVal();
// 输出如下
*******
Window {parent: Window, opener: null, top: Window, length: 0, frames: Window, …}
*******

Функция getVal — это стрелочная функция, а this в методе — это this, следующее за родителем.

После выполнения external() верните внутреннюю функцию закрытия

Затем выполнить внутреннюю функцию закрытия, а внутренняя функция закрытия также является обычной функцией, все еще следующей [кто звонит, кто указывает на], нет прямого вызова объекта, но вызывается самое внешнее «опущенное» окно, так внутренний Это указывает на окно.

Область действия функции закрытия такая же, как и у родительской функции.Мы можем понять, что область действия функции закрытия выскочила из родительской функции, но вы также можете получить прямой доступ к переменным параметрам в родительской функции и т. д. мощный).

Внутренний здесь фактически находится в той же области, что и внешний.

Измените this функции стрелки

Мы можем использовать Bind, чтобы изменить this родительской внутренней функции, чтобы изменить указатель this дочерней стрелочной функции getVal.

пример:

function outer(){
    var inner = function(){
        var obj = {};
        obj.getVal=()=>{
            console.log("*******");
            console.log(this);
            console.log("*******");
        }
        return obj;
    };
    return inner; 
}
outer().bind(outer)().getVal();
//输出如下
*******
ƒ outer(){
    var inner = function(){
        var obj = {};
        obj.getVal=()=>{
            console.log("*******");
            console.log(this);
            console.log("*******");
        }
  …
*******

Это выполняет внешний метод и возвращает внутреннюю функцию.

Затем мы меняем внутренний указатель this и используем bind, чтобы указать внутренний this на внешний.

Мы видим, что результатом этого является внешняя функция. Здесь мы успешно изменили указатель this в getVal.

this функции стрелки изменилось с изменением this родительского элемента. (На самом деле это правда, this функции стрелки - это просто назначение контекста родительской функции this)

Описание стрелочных функций в статье Руан Ифэн

Копируем основные моменты исходного текста следующим образом:

Есть несколько предостережений по использованию стрелочных функций.

(1) Объект this в теле функции — это объект, в котором он определен, а не объект, в котором он используется.

Из четырех пунктов, приведенных выше, особенно следует отметить первый. Указатель этого объекта является изменяемым, но в стрелочных функциях он фиксированный.

Здесь выражены два основных момента:

  • Объект this в теле функции — это объект, в котором он был определен.

Да, можно понять, что этот объект в функции стрелки указывает на родительский объект в лексической области видимости, когда он определен.

  • Указатель этого объекта переменный, но в стрелочных функциях он фиксированный.

Объект this обычной функции указан для выполнения и, конечно же, является переменным. Это в стрелочной функции фиксировано, и оно зафиксировано в родительском контексте this.

вывод, как показано ниже:

this стрелочной функции — это обычная переменная, указывающая на this родительской функции, и этот указатель никогда не изменится и не может быть изменен.

Но если вам нужно изменить this функции стрелки, вы можете изменить this родительской функции стрелки, чтобы изменить this дочерней функции стрелки. (Основная причина в том, что стрелочные функции не имеют this, но используют родительский this во время выполнения).

Если есть какие-то упущения, пожалуйста, поправьте меня~. Добавить мою личную учетную запись WeChat: lqyygyss

Добро пожаловать, чтобы обратить внимание на мою общедоступную учетную запись WeChat, давайте вместе будем надежным интерфейсом!

follow-me