Функции 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
Для лучшего понимания обратитесь к этой статье:
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.