Функции JavaScript, часть 2: неявные параметры функций и вызов функций

Это продолжение первой статьи:



В этом блоге мы обсудим следующие темы:

  • Неявные параметры функции
  • Вызов функций различными способами

1. Неявные параметры функции: “arguments” и this

Из Части 1 мы поняли разницу между параметрами функции (переменными, перечисленными как часть определения функции) и аргументами функции (значениями, передаваемыми функции при ее вызове). ). Поэтому, когда мы вызываем функцию, функции неявно передаются два параметра: argumentsи this.

Эти параметры не указаны явно в сигнатуре функции, поэтому они считаются неявными.

1.1 arguments параметр

Все аргументы, передаваемые функции, собираются в параметре arguments. Он используется для доступа ко всем аргументам функции. Это позволяет нам использовать перегрузку функций, что JavaScript изначально не поддерживает.
Использование параметра arguments резко сократилось с момента появления параметра rest в ES6. Давайте посмотрим, как работают аргументы реализации.

Объект arguments имеет правильную длину для указания количества аргументов. Индивидуальные значения аргументов могут быть получены с помощью записи // индексирования массива; например, аргументы[6].

Sample 1 :
// https://www.w3schools.com/js/js_function_parameters.asp
x = findMax(1, 123, 500, 115, 44, 88);
function findMax() {
   let max = -Infinity;
     for (let i = 0; i < arguments.length; i++) {
       if (arguments[i] > max) {
       max = arguments[i];
       }
     }
     return max;
 }
console.log(x)
// output
500
Sample 2 :
function nowhere(a, b, c) {
    console.log(a, b, c);
    console.log(arguments)
}
// output
nowhere(3,4,5,6)
3 4 5
[Arguments] { '0': 3, '1': 4, '2': 5, '3': 6 }

Строгий режим:

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

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

"use strict"
function handleBomb(country) {
 console.log(arguments)
 arguments[0] = 'Japan';
 console.log(country, arguments[0])
}
handleBomb('USA')
// output
[Arguments] { '0': 'USA' }
USA Japan

Для лучшего понимания обратитесь к этой статье:



Учебное пособие по Javascript «use strict с примерами
Редактировать описаниеqnimate.com»



1.2 this параметр

Параметр this является жизненно важным компонентом объектно-ориентированного JavaScript и относится к объекту, связанному с вызовом функции. По этой причине она называется функцией context.

Контекст функции — это понятие для тех, кто пришел из объектно-ориентированных языков, таких как Java. Они могут подумать, что поняли this, поскольку в таких языках this указывает на экземпляр класса, в котором определен метод.

Но, как мы увидим в следующем контексте, this в JavaScript зависит от способов вызова функции. Потому что понимание точной природы параметра this является одним из самых важных столпов объектно-ориентированного JavaScript.

2. Вызов функции различными способами

2.1 Вызов как функция

Не путайтесь с заголовком, вызов «как функция» должен отличать его от других механизмов вызова: методов, конструктора и apply /call.

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

// function declaration invoked as a function
function hero() {};
hero()
// function expression invoked as a function
var superman = function () {};
superman();
// Immediately invoked function expression, invoked as function
(function(){})()

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

2.2 Вызов как метод

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

const hero = {}
hero.superman = function(){};
hero.superman()

Давайте разберемся со словом метод здесь. Исходя из объектно-ориентированного опыта, вы помните, что объект, которому принадлежит метод, доступен в теле метода как this. Здесь происходит то же самое. Когда функция вызывается как метод объекта, этот объект становится контекстом функции и доступен внутри функции через параметр this. Это означает, что JavaScript позволяет писать объектно-ориентированный код.

function provideContext() {
 this.exceptionHero = 'Vision'
 return this;
}
const contextHandler = {
 orgName: 'Marvel',
 provideSuperHeroContext: provideContext
}
console.log('---1---')
console.log(provideContext())
console.log('---2---')
console.log(contextHandler.provideSuperHeroContext())
// output
---1---
Object [global] {
  global: [Circular],
  clearInterval: [Function: clearInterval],
  clearTimeout: [Function: clearTimeout],
  setInterval: [Function: setInterval],
  setTimeout: [Function: setTimeout] {
    [Symbol(nodejs.util.promisify.custom)]: [Function]
  },
  queueMicrotask: [Function: queueMicrotask],
  clearImmediate: [Function: clearImmediate],
  setImmediate: [Function: setImmediate] {
    [Symbol(nodejs.util.promisify.custom)]: [Function]
  },
  exceptionHero: 'Vision'
}
---2---
{
  orgName: 'Marvel',
  provideSuperHeroContext: [Function: provideContext],
  exceptionHero: 'Vision'
}

Примечание. Чтобы писать на JavaScript объектно-ориентированным способом, функции должны вызываться как методы. Это позволяет вам использовать this для ссылки на объект «owner» метода внутри любого метода, что является фундаментальной идеей объектно-ориентированного программирования.

2.3 Вызов в качестве конструктора

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

Для вызова функции в качестве конструктора перед вызовом функции ставится ключевое слово new.

function Marvel() {
}
const marvel = new Marvel()

2.3.1 Конструкторы — это стероиды функции

Давайте проверим это:

function HeroOrg() {
 this.groundRules = function() {
  return this;
 }
}
const marvel = new HeroOrg()
const dc = new HeroOrg()
console.log('---1---')
console.log(marvel.groundRules() === dc.groundRules())
console.log('---2---')
console.log(marvel.groundRules() === marvel)
//output
---1---
false
---2---
true

Мы создаем функцию с именем HeroOrg, которая будет использоваться для построения. Мы создаем два экземпляра marvel и dc. Конструктор создал для этого объекта свойство с именем groundRules, которому назначается функция, превращающая эту функцию в метод вновь созданного объекта.

При вызове конструктора происходит несколько вещей:

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

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

2.3.2 Значения, возвращаемые конструкторами

function Hero() {
 this.name = 'Superman'
 return 'sucess'
}
const hero1 = new Hero()
const hero2 = Hero()
console.log('---1---')
console.log(hero1)
console.log('---2---')
console.log(hero2)
//output
---1---
Hero { name: 'Superman' }
---2---
sucess

Как видно из приведенного выше примера, когда функция вызывается как конструктор, возвращается новый объект, созданный конструктором. Если мы вызовем функцию без ключевого слова new, то будет возвращено окончательное значение оператора return или undefined.

2.4 Использование методов apply, call и bind

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

2.4.1 ПРИМЕНИТЬ

Чтобы вызвать функцию методом apply, мы передаем два параметра в apply, объект как функциональный контекст и массив значений.

Для получения более подробной информации проверьте это:



function fly() {
 console.log(this.org)
 console.log(...arguments)
}
const customPower = { org: 'marvel'}
fly.apply(customPower, ['thor', 'ironman', 'vision'])
// output
marvel
thor ironman vision

Поскольку мы можем установить, что мы передали customPower в качестве контекста функции fly через apply. Если бы это был обычный вызов, this указывало бы здесь на глобальный объект в качестве контекста, но мы перезаписываем его нашим пользовательским объектом в качестве контекста.

const heroOrg = {
 fly: function () {
  console.log(this.org)
  console.log(...arguments)
 }
}
const customPower = { org: 'marvel'}
heroOrg.fly.apply(customPower, ['thor', 'ironman', 'vision'])
//output
marvel
thor ironman vision 

2.4.2 ЗВОНОК

Аналогичным образом используется и метод call. Просто вместо массива аргументов мы передаем список аргументов.

function fly() {
 console.log(this.org)
 console.log(...arguments)
}
const customPower = { org: 'marvel'}
fly.call(customPower, 'thor', 'ironman', 'vision')
//output
marvel
thor ironman vision
const heroOrg = {
 fly: function () {
  console.log(this.org)
  console.log(...arguments)
 }
}
const customPower = { org: 'marvel'}
heroOrg.fly.call(customPower, 'thor', 'ironman', 'vision')
//output
marvel
thor ironman vision

2.4.3 ПРИВЯЗКА

Метод bind доступен для всех функций и предназначен для созданияи возврата новойфункции, привязанной к переданному объекту.

const marvel = { name: "Marvel", leader: 'Nick Fury' }
const dc = { name: "DC", leader: 'Batman'}
function printOrgnizationDetail() {
 console.log(`Name: ${this.name}, Lead: ${this.leader}`)
}
const marvelOrg = printOrgnizationDetail.bind(marvel)
const dcOrg = printOrgnizationDetail.bind(dc)
marvelOrg()
dcOrg()
//output
Name: Marvel, Lead: Nick Fury
Name: DC, Lead: Batman

ПРИМЕЧАНИЕ. Для функции стрелки (лямбда-функции) существует ограничение. «вызов», «связать» и «применить» нельзя использовать с функциями массива. Для лучшего понимания функции стрелки проверьте это:



И это все, что касается продвижения в функциях JavaScript. Я надеюсь, что вы нашли это полезным. Спасибо за чтение.

Дополнительные материалы на PlainEnglish.io. Подпишитесь на нашу бесплатную еженедельную рассылку новостей. Подпишитесь на нас в Twitter и LinkedIn. Присоединяйтесь к нашему сообществу Discord.