Поднятие переменных:

var предоставляет область действия функции

Javascript придерживается лексической области видимости — переменные, объявленные снаружи, доступны внутри.

Подъем означает подъем или перемещение вещей наверх (вверх).

function a() {
 console.log(x);
 var x = 10;
}
a()
Output: undefined

В приведенном выше примере x определен в третьем выражении, но все равно, когда мы пытаемся получить доступ, мы получаем undefined вместо ошибки ссылки. Такое поведение связано с подъемом.

Таким образом, подъем переменной в Javascript перемещает функцию и объявление переменной наверх.

var x = 20;
function a() {
 console.log(x);
 var x = 10;
}
a()
Output: Undefined

Переменная, не объявленная с ключевым словом var, поднимается в глобальную область/область окна.

function hoisting() {
 a = 20;
 var b = 100;
}
hoisting();
console.log(a)
Output: 20

Если мы используем javascript в строгом режиме с помощью "использовать строгий", мы получим ошибку, если попытаемся использовать неопределенные переменные, и выдадим тихие ошибки только во время интерпретации.

С помощью ключевого слова let мы получим область действия блока, несмотря на глобальную область действия.

console.log(a);
let a = 10;
output:ReferenceError: a is not defined

Подъем в функциях:

  1. Объявленная функция перемещается вверх
  2. Функциональные выражения ведут себя как простые переменные.

Правила:

  1. Присвоение переменной имеет приоритет над объявлением функции
  2. Объявления функций имеют приоритет над объявлениями переменных.

Замыкания: — наиболее часто задаваемые вопросы

Javascript придерживается лексической области видимости — переменные, объявленные снаружи (верхняя область видимости), автоматически становятся доступными внутри.

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

function a() {
 let x = 1;
 return () => {
  console.log(x)
 }
}
var c = a();
c();
Output: 1

Закрытие в цикле:

for (let i =0; i < 3; i ++) {
 let f = () => {
  console.log(i);
 }
f();
}
Output: 0 1 2
for (let i =0; i < 3; i ++) {
 setTimeout(() => {
  console.log(i);
 }, 1000)
}
Output: 0 1 2
for (var i =0; i < 3; i ++) {
 setTimeout(() => {
  console.log(i);
 }, 1000)
}
Output: 3 3 3

В приведенном выше примере, когда мы использовали асинхронную вещь, мы увидели разницу между var и let. Это происходит из-за области действия блока let (функция содержит ссылку) и области действия функции var. Таким образом, с помощью let он каждый раз создавал отдельные переменные, а с помощью var он просто обновлял их и использовал.

Чтобы заставить его работать с var , мы можем использовать IIFE-, который заставляет его работать сразу:

for (var i =0; i < 3; i ++) {
 ((i) => {
  setTimeout(() => {
   console.log(i);
   }, 1000)
 })(i)
}
Output: 0 1 2

Звоните, связывайтесь и подавайте заявку:

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

Вызов: присоединение объекта к методу и передача всех параметров

const data = {
 value: 10
}
const add = function(value2) {
 return this.value + value2
}
console.log(add.call(data, 20))
Output: 30

Apply:присоединение объекта к методу, но одно отличие по сравнению с вызовом заключается в том, что мы можем передавать массив вместо отдельных аргументов, если аргументов много.

const data = {
 value: 10
}
const add = function(value2, value3, value4) {
 return this.value + value2 + value3 + value4
}
console.log(add.call(data, [20, 30, 40]))
Output: 100

Bind: присоединение объекта к методу, а взамен мы получаем еще одну функцию вместо выполняемой функции. Как следует из названия, он связывает данные с функцией и возвращает функцию.

const data = {
 value: 10
}
const add = function(value2) {
 return this.value + value2
}
const final = add.bind(data);
console.log(final(20))
Output: 30

это ключевое слово:

это объект, выполняющий текущую функцию.

если функция является частью объекта, то this ссылается на сам объект.

'use strict'
const testing = {
 name: 'Rishabh',
 test1() {
  console.log(this);
 }
}
testing.test1()
Output: { name: 'Rishabh', test1: [Function: test1] }

если функция является обычной функцией, то эта ссылка на глобальный объект (объект окна)

function testing() {
 console.log(this);
}
testing()
Output: Object [global] {
  DTRACE_NET_SERVER_CONNECTION: [Function],
  DTRACE_NET_STREAM_END: [F

function testing(name) {
 this.name = name;
 console.log(this);
}
new testing('Rishabh') // New operator creates a new empty object
Output: testing{ name: 'Rishabh' }

Различные случаи с этим:

  1. В глобальном масштабе:
this.name = "Rishabh";
console.LOG(this)

2. Невозможно напрямую использовать это внутри внутренней функции:

"use strict"
var name = "Rishabh"; // or we can use this.name - both are same
function testing() {
  console.log(this.name)
  function tes() {
    console.log(this.name);
  }
  tes()
}
testing.call(this)
Output:
Rishabh
undefined

Решение верхней задачи возможно тремя способами:

"use strict"
var name = "Rishabh"; // or we can use this.name - both are same
function testing() {
 let that = this; 
console.log(this.name)
  function tes() {
    console.log(that.name); // Implicit Binding
  }
  tes()
}
testing.call(this)
Output:
Rishabh
Rishabh
OR
var name = "Rishabh"; // or we can use this.name - both are same
function testing() {
console.log(this.name)
  function tes() {
    console.log(this.name);
  }
  tes.call(this) // or we can use apply and bind also -- explcit binding
}
testing.call(this)
Output:
Rishabh
Rishabh
OR
var name = "Rishabh"; // or we can use this.name - both are same
function testing() {
console.log(this.name)
  const tes = ()  => {
    console.log(this.name);
  }
  tes() // or we can use apply and bind also - explicit
}
testing.call(this)
Output:
Rishabh
Rishabh

var a = «ришабх»

console.log(это.а); // ришаб

пусть a = «ришабх»

console.log(это.а); // неопределенный

Приоритет привязки ключевого слова «это»

  • Сначала он проверяет, вызывается ли функция с ключевым словом new.
  • Во-вторых, он проверяет, вызывается ли функция с помощью метода call() или apply(), что означает явную привязку.
  • В-третьих, он проверяет, вызывается ли функция через объект контекста (неявная привязка).
  • Глобальный объект по умолчанию (не определен в случае строгого режима).

Функции стрелки:

Способ написания функций, представленный в ES6.

Сокращены реализации функций:

const a = function(x) {
 return x;
}
is Equivalent to 
const a = (x) => x;

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

var name = "Rishabh"; // or we can use this.name - both are same
function testing() {
console.log(this.name)
  const tes = ()  => {
    console.log(this.name);
  }
  tes() // or we can use apply and bind also - explicit
}
testing()
Output:
Rishabh
Rishabh
And
var name = "Rishabh"; // or we can use this.name - both are same
function testing() {
  console.log(this.name)
  function tes() {
    console.log(this.name);
  }
  tes()
}
testing()
Output:
Rishabh
undefined

Прототип:

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

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

var testing = function (name) {
 this.name = name;
 this.getName = function() {
  return this.name;
}
}
var test1 = new testing('Rishabh')
var test2 = new testing('jain');
console.log(test1.getName());
console.log(test2.getName());
Output:
Rishabh
Jain

С прототипами на одну копию функции будут ссылаться все созданные объекты.

var testing = function (name) {
 this.name = name;
}
testing.prototype.getName = function() {
 return this.name;
}
var test1 = new testing('Rishabh')
var test2 = new testing('jain');
console.log(test1.getName());
console.log(test2.getName());
Output:
Rishabh
Jain

Наследование с прототипами (несколько классов):

//Parent Class
var Institution = function(name) {
 this.name = name;
}
Institution.prototype.institutionName = function() {
 console.log(this.name);
}
// Child Class
var LearningStreams = function(streamName, name) {
 Institution.call(this, name);
 this.streamName = streamName;
}
// Setting prototype of Parent Class to be available in Child Class
LearningStreams.prototype = Object.create(Institution.prototype);
// Setting constructor to reference to itself
LearningStreams.prototype.constructor = LearningStreams;
// To shadow methods -- not overriding as in prototype it first looks into its own methods and then goes to upper level
LearningStreams.prototype.institutionName = function() {
 console.log('Institute name is', this.name);
}
const stream1 = new LearningStreams('Mechanical', 'GGSIPU');
stream1.institutionName();
Output: Institute name is GGSIPU

Объектно-ориентированное программирование Javascript: все о наследовании прототипов

Конструкторы: создают экземпляры свойств объекта, который мы создаем.

const Test = function(name) {
 this.name = name;
}
const obj = new Test('Rishabh');
console.log(obj)
Output: 
Test { name: 'Rishabh' } // also some prototype property also attached

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

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

  1. Использование утилиты «use strict» введено в ECMA5.
  2. Проверяем, создаем ли мы экземпляр без нового оператора. — if (!new.target) выдает ‘ошибку’

Object.create(): Как мы видели, это делает возможным наследование прототипов.

Предоставляет способ создания объекта:

const obj1 = Object.create(Object.prototype);
// Object{__proto__}
const obj2 = Object.create(Object.prototype);
// Object {__proto__}
const obj3 = Object.create(null)
//Object{}

Прототип — это одна из основных концепций ООП в JS, которую мы уже рассмотрели.

Object.setPrototypeOf(destination, source): обеспечивает способ наследования прототипа.

var testing1 = {
 method1(){
  return 'Method 1';
 }
}
var testing2 = {
 method2(){
  return 'Method 2';
 }
}
Object.setPrototypeOf(testing2, testing1);
console.log(testing2.method1())
Output: Method 1

Когда оба объекта имеют одинаковые методы:

var testing1 = {
 method1(){
  return 'Method 1 from testing1';
 }
}
var testing2 = {
 method1(){
  return 'Method 1 from testin2';
 }
}
Object.setPrototypeOf(testing2, testing1);
console.log(testing2.method1())
Output: Method 1 from testin2

Использование метода-прототипа, даже если метод существует в дочернем классе:

var testing1 = {
 method1(){
  return 'Method 1 from testing1';
 }
}
var testing2 = {
 method1(){
  return super.method1();
 }
}
Object.setPrototypeOf(testing2, testing1);
console.log(testing2.method1())
Output: Method 1 from testing1

Object.assign() — копирует свойства одного объекта в другой, как setPrototypeOf, но имеет некоторые отличия. Также Object.assign также используется для создания глубокой копии.

В приведенном ниже примере мы видим, что когда мы создаем object.assign, метод переопределяется новым методом (из которого создается). Также он копирует свойство непосредственно в целевой объект, а не в прототип.

var testing1 = {
 method1(){
  return 'Method 1 from testing1';
 }
}
var testing2 = {
 method1(){
  return 'Method 1 from testing2';
 }
}
Object.assign(testing2, testing1);
console.log(testing2.method1())
Output: Method 1 from testing1

Создание нового объекта с помощью assign, а также использование его в конструкторах:

// Creating new object
Object.assign({}, {name: 'Rishabh'});
//Using it in constructor - Below 2 are equivalent
function test(name, age) {
 this.name = name;
 this.age = age;
}
function test(name, age) {
 Object.assign(this, { name, age })
}

Классы в Javascript:

Пришло ключевое слово класса ES2015. В javascript классы являются конструктором функций с прототипом, только если мы видим их базовую реализацию.

class Profile {
 constructor(name, age) {
  this.name = name;
  this.age = age;
 }
}

Также в качестве метода-прототипа добавлен метод создания внутри класса:

Расширение в классах ES6:

В подпольном ключе расширения используйте только наследование прототипа.

class MyProfile {
 constructor(name, age) {
  Object.assign(this, { name, age })
}
 profileData() {
  console.log(`Name: ${this.name} ||  Age: ${this.age}`)
 }
}
class ProgammingLanguage extends MyProfile {
 constructor(name, age, language) {
  super(name, age);
   this.language = language;
}
}
console.dir(ProgammingLanguage)

Object.defineProperty: для создания константной переменной (используется, когда нет модификатора константы.

Object.defineProperty(window, 'test', 123);
test = 10;
console.log(test);

Для части 2: https://medium.com/@rishabh171192/javascript-important-topics-and-explanation-part-2-f4d99ee9eff7

В случае каких-либо вопросов и предложений, пожалуйста, свяжитесь со мной https://www.linkedin.com/in/rishabh-jain-a5978583/ или отправьте письмо по адресу @[email protected]