Кирилл Хаим Щербина

ФУНКЦИИ И КЛАССЫ КОНСТРУКТОРА ES2105

Начиная с 2015 года вместо создания функций-конструкторов (функция User…) мы пишем классы и определяем функцию с именем «конструктор» -> class User {structor(arg) {} }.

Это просто синтаксический сахар. Мы не превратили Javascript в объектно-ориентированную парадигму, основанную на классах.

Идея функции-конструктора, а теперь и «класса», заключается в том, что когда мы хотим, например, создать пользователя. Мы будем использовать объект для этого.

const bobby = {имя: 'bobby', возраст: 20, родной город: 'Филадельфия'}

Но тогда представьте, что многие такие пользователи с одинаковыми характеристиками выйдут из-под контроля. Таким образом, чтобы стандартизировать атрибуты, которые мы назначаем объекту, мы могли бы просто сделать:

function User(name, age, hometown) {
this.name = name
this.age = age
this.hometown = hometown
}
// calling ‘new’ tells JS to 1) create a new object and 2)to automatically return the new object
const bobby = new User(‘bobby’, 20, ‘Philadelphia’)
// {name: ‘bobby’, age: 20, hometown: ‘Philadelphia’}

Теперь с ES6 наш код будет выглядеть примерно так:

class User {
constructor(name, email) {
this.name = name;
this.email = email;
}
sayHello() {
console.log(`Hello, my name is ${this.name}`);
 }
}
let sarah = new User(‘sarah’, ‘[email protected]’);
sarah.sayHello();

ПРОТОТИПЫ

Идея прототипов заключается в том, что если бы мы объявили функцию внутри наших функций-конструкторов, то каждый экземпляр имел бы эту функцию, то есть НОВЫЙ экземпляр этой функции.

При использовании прототипов мы позволяем каждому экземпляру иметь доступ к этой функции, но все экземпляры указывают на эту ОДНУ функцию. Это подавляет нашу память.

ЭТО

Короче говоря, this ссылается на объект, который получает вызов метода. Это позволяет нам получить доступ к объекту, получающему метод, изнутри вызова метода.

Тем не мение….

Значение этого изменяется в зависимости от того, где оно находится.

-Вне любой функции это относится к глобальному объекту. В веб-браузерах это окно

-Внутри объектного метода это относится к объекту, который получил вызов метода

-Внутри автономной функции это будет либо глобальный объект по умолчанию, либо не определено

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

Можно заставить «это» сохранить свое значение. Это делается с помощью bind(), call() или apply().

НАБЛЮДАЕМ ЗА ЭТИМ ИЗМЕНЕНИЕМ:

let person = {
greet: function() {
return this;
  }
};
person.greet() == person;
// true
let greetFn = person.greet;
greetFn() == person; // false
greetFn(); // window
person.greet() == person; // true

Итак, давайте пройдемся по коду выше. Мы устанавливаем наше свойство приветствия объекта person так, чтобы оно указывало на ту же функцию, и видим, что когда мы вызываем person.greet(), это относится к объекту person.

Сложность возникает, когда мы пишем letgreetFn = person.greet. Что это делает, так это назначает локальную переменную welcomeFn для ссылки на функцию в объекте человека. Однако эта локальная переменная вообще не относится к объекту человека. Он имеет нулевое знание объекта человека. Он указывает только на функцию. Затем мы вызываем функцию, вызвав welcomeFn(). При этом мы не вызываем свойство объекта, мы просто вызываем функцию.

Когда функция вызывается, это относится к окну, нашему глобальному объекту.

ФУНКЦИИ СТРЕЛКИ

// using our old standard function
const oldStandardFunction = function() {
return ‘old standard functions rule!’;
};
// updating to use an arrow function
const arrowFunction = () => {
return ‘Arrow functions are great too!’;
};

Другой способ написать стрелочные функции:

const oldSquare = function(n) {
return n * n;
};
const newSquare = n => n * n;
//this will only work if the method is written on one line and only one argument (otherwise we must include argument parentheses). Also worth noting is that we cannot mix the two

Стрелочные функции не имеют идентификаторов, поэтому они всегда анонимны. Мы можем установить указатель на стрелочную функцию или передать стрелочную функцию в качестве аргумента другой функции:

const square = n => n * n
// note that while the above function is anonymous, we have assigned it to the variable ‘square’
[1, 2, 3].map(n => n * n) // [1, 4, 9]
[1, 2, 3].map(square); // [1, 4, 9]

Важно помнить, что в JavaScript функции являются «объектами первого класса». Они могут передаваться, объявляться, обрабатываться и иметь свойства и методы, как и любой другой объект.

Мы знаем, что объявление функции (не вызов!) само по себе имеет возвращаемое значение, потому что мы только что присвоили его переменной Square выше. Возвращаемое значение объявления функции — это указатель на сам объект функции.

Стрелочные функции и «это»

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

const person = {
firstName: ‘bob’,
greet: function() {
return () => {
return `Hi, I’m ${this.firstName}`;
  };
 }
};
person.greet()();
// “Hi, I’m bob”

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

const person = {
firstName: ‘bob’,
greet: function() {
return [1, 2, 3].map(() => this);
  }
};
person.greet()
// [{firstName: “bob”, greet: ƒ}, {firstName: “bob”, greet: ƒ}, {firstName: “bob”, greet: ƒ}]
[1, 2, 3].map(() => this);
// [Window, Window, Window]

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

Надеюсь, вам понравилась эта статья. Пожалуйста, хлопните в ладоши, если вы это сделали. Пока!