Что такое метод в javascript
Перейти к содержимому

Что такое метод в javascript

  • автор:

Введение в методы и свойства

Материал на этой странице устарел, поэтому скрыт из оглавления сайта.

Более новая информация по этой теме находится на странице https://learn.javascript.ru/object.

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

Такие функции называют «методами», а значения – «свойствами». Здесь мы рассмотрим основы использования свойств и методов.

Свойство str.length

У строки есть свойство length , содержащее длину:

alert( "Привет, мир!".length ); // 12

Можно и записать строку в переменную, а потом запросить её свойство:

var str = "Привет, мир!"; alert( str.length ); // 12

Метод str.toUpperCase()

Также у строк есть метод toUpperCase() , который возвращает строку в верхнем регистре:

var hello = "Привет, мир!"; alert( hello.toUpperCase() ); // "ПРИВЕТ, МИР!"

Вызов метода – через круглые скобки!

Обратите внимание, для вызова метода обязательно нужны круглые скобки.

Посмотрите, например, результат обращения к toUpperCase без скобок:

var hello = "Привет"; alert( hello.toUpperCase ); // function. 

Метод – это встроенная команда («функция», мы поговорим о них позже), которую нужно вызвать для получения значения. При обращении без скобок мы получим саму эту функцию. Как правило браузер выведет её как-то так: «function toUpperCase() < . >» .

А чтобы получить результат – нужно произвести её вызов, добавив скобки:

var hello = "Привет"; alert( hello.toUpperCase() ); // ПРИВЕТ

Более подробно с различными свойствами и методами строк мы познакомимся в главе Строки.

Метод num.toFixed(n)

Есть методы и у чисел, например num.toFixed(n) . Он округляет число num до n знаков после запятой, при необходимости добивает нулями до данной длины и возвращает в виде строки (удобно для форматированного вывода):

var n = 12.345; alert( n.toFixed(2) ); // "12.35" alert( n.toFixed(0) ); // "12" alert( n.toFixed(5) ); // "12.34500"

Детали работы toFixed разобраны в главе Числа.

Обращение к методам чисел

К методу числа можно обратиться и напрямую:

alert( 12.34.toFixed(1) ); // 12.3

…Но если число целое, то будет проблема:

Методы объектов JavaScript

В определении функции ключевое слово this ссылается на «владельца» функции.

Так, в примере выше this это объект person, который «владеет» функцией fullName.

Другими словами, this.firstName означает свойство firstName данного объекта.

Подробнее о ключевом слове this см. главу Ключевое слово this

Методы JavaScript

Методы JavaScript это действия, которые можно выполнить с объектами.

Метод JavaScript это свойство, содержащее определение функции.

Свойство Значение
firstName John
lastName Doe
age 50
eyeColor blue
fullName function()

Методы это функции, хранящиеся как свойства объекта.

Обращение к методам объекта

Чтобы вызвать метод объекта, используется следующий синтаксис:

Обычно обращение fullName() указывает на метод объекта person, а fullName на его свойство.

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

В следующем примере мы обращаемся к методу fullName() объекта person:

 name = person.fullName(); 

Если вызвать свойство fullName, без круглых скобок (), то будет возвращено определение функции:

 name = person.fullName; 

Использование встроенных методов

В следующем примере используется метод toUpperCase() объекта String, чтобы преобразовать текст в верхний регистр:

 var message = "Hello world!"; var x = message.toUpperCase(); 

После выполнения кода этого примера, значением переменной x будет строка «HELLO WORLD!».

Добавление методов в объект

Добавить новый метод в объект очень просто:

 person.name = function () < return this.firstName + " " + this.lastName; >; 

Методы объекта, «this»

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

// Объект пользователя let user = < name: "John", age: 30 >;

И так же, как и в реальном мире, пользователь может совершать действия: выбирать что-то из корзины покупок, авторизовываться, выходить из системы, оплачивать и т.п.

Такие действия в JavaScript представлены функциями в свойствах.

Примеры методов

Для начала давайте научим нашего пользователя user здороваться:

let user = < name: "John", age: 30 >; user.sayHi = function() < alert("Привет!"); >; user.sayHi(); // Привет!

Здесь мы просто использовали Function Expression (функциональное выражение), чтобы создать функцию приветствия, и присвоили её свойству user.sayHi нашего объекта.

Затем мы можем вызвать ee как user.sayHi() . Теперь пользователь может говорить!

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

Итак, мы получили метод sayHi объекта user .

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

let user = < // . >; // сначала, объявляем function sayHi() < alert("Привет!"); >// затем добавляем в качестве метода user.sayHi = sayHi; user.sayHi(); // Привет!

Объектно-ориентированное программирование

Когда мы пишем наш код, используя объекты для представления сущностей реального мира, – это называется объектно-ориентированным программированием или сокращённо: «ООП».

ООП является большой предметной областью и интересной наукой самой по себе. Как выбрать правильные сущности? Как организовать взаимодействие между ними? Это – создание архитектуры, и на эту тему есть отличные книги, такие как «Приёмы объектно-ориентированного проектирования. Паттерны проектирования» авторов Эрих Гамма, Ричард Хелм, Ральф Джонсон, Джон Влиссидес или «Объектно-ориентированный анализ и проектирование с примерами приложений» Гради Буча, а также ещё множество других книг.

Сокращённая запись метода

Существует более короткий синтаксис для методов в литерале объекта:

// эти объекты делают одно и то же user = < sayHi: function() < alert("Привет"); >>; // сокращённая запись выглядит лучше, не так ли? user = < sayHi() < // то же самое, что и "sayHi: function()" alert("Привет"); > >;

Как было показано, мы можем пропустить ключевое слово «function» и просто написать sayHi() .

Нужно отметить, что эти две записи не полностью эквивалентны. Есть тонкие различия, связанные с наследованием объектов (что будет рассмотрено позже), но на данном этапе изучения это неважно. Почти во всех случаях сокращённый синтаксис предпочтителен.

Ключевое слово «this» в методах

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

Например, коду внутри user.sayHi() может потребоваться имя пользователя, которое хранится в объекте user .

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

Значение this – это объект «перед точкой», который используется для вызова метода.

let user = < name: "John", age: 30, sayHi() < // "this" - это "текущий объект". alert(this.name); >>; user.sayHi(); // John

Здесь во время выполнения кода user.sayHi() значением this будет являться user (ссылка на объект user ).

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

let user = < name: "John", age: 30, sayHi() < alert(user.name); // "user" вместо "this" >>;

…Но такой код ненадёжен. Если мы решим скопировать ссылку на объект user в другую переменную, например, admin = user , и перезапишем переменную user чем-то другим, тогда будет осуществлён доступ к неправильному объекту при вызове метода из admin .

Это показано ниже:

let user = < name: "John", age: 30, sayHi() < alert( user.name ); // приведёт к ошибке >>; let admin = user; user = null; // перезапишем переменную для наглядности, теперь она не хранит ссылку на объект. admin.sayHi(); // TypeError: Cannot read property 'name' of null

Если бы мы использовали this.name вместо user.name внутри alert , тогда этот код бы сработал.

«this» не является фиксированным

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

В следующем примере нет синтаксической ошибки:

function sayHi()

Значение this вычисляется во время выполнения кода, в зависимости от контекста.

Например, здесь одна и та же функция назначена двум разным объектам и имеет различное значение «this» в вызовах:

let user = < name: "John" >; let admin = < name: "Admin" >; function sayHi() < alert( this.name ); >// используем одну и ту же функцию в двух объектах user.f = sayHi; admin.f = sayHi; // эти вызовы имеют разное значение this // "this" внутри функции - это объект "перед точкой" user.f(); // John (this == user) admin.f(); // Admin (this == admin) admin['f'](); // Admin (нет разницы между использованием точки или квадратных скобок для доступа к объекту)

Правило простое: если вызывается obj.f() , то во время вызова f , this – это obj . Так что, в приведённом выше примере это либо user , либо admin .

Вызов без объекта: this == undefined

Мы даже можем вызвать функцию вообще без объекта:

function sayHi() < alert(this); >sayHi(); // undefined

В строгом режиме ( «use strict» ) в таком коде значением this будет являться undefined . Если мы попытаемся получить доступ к this.name – это вызовет ошибку.

В нестрогом режиме значением this в таком случае будет глобальный объект ( window в браузерe, мы вернёмся к этому позже в главе Глобальный объект). Это – исторически сложившееся поведение this , которое исправляется использованием строгого режима ( «use strict» ).

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

Последствия свободного this

Если вы до этого изучали другие языки программирования, то вы, вероятно, привыкли к идее «фиксированного this » – когда методы, определённые в объекте, всегда имеют this , ссылающееся на этот объект.

В JavaScript this является «свободным», его значение вычисляется в момент вызова метода и не зависит от того, где этот метод был объявлен, а скорее от того, какой объект вызывает метод (какой объект стоит «перед точкой»).

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

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

У стрелочных функций нет «this»

Стрелочные функции особенные: у них нет своего «собственного» this . Если мы ссылаемся на this внутри такой функции, то оно берётся из внешней «нормальной» функции.

Например, здесь arrow() использует значение this из внешнего метода user.sayHi() :

let user = < firstName: "Ilya", sayHi() < let arrow = () =>alert(this.firstName); arrow(); > >; user.sayHi(); // Ilya

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

Итого

  • Функции, которые находятся в свойствах объекта, называются «методами».
  • Методы позволяют объектам «действовать»: object.doSomething() .
  • Методы могут ссылаться на объект через this .

Значение this определяется во время исполнения кода.

  • При объявлении любой функции в ней можно использовать this , но этот this не имеет значения до тех пор, пока функция не будет вызвана.
  • Функция может быть скопирована между объектами (из одного объекта в другой).
  • Когда функция вызывается синтаксисом «метода» – object.method() , значением this во время вызова является object .

Также ещё раз заметим, что стрелочные функции являются особенными – у них нет this . Когда внутри стрелочной функции обращаются к this , то его значение берётся извне.

Задачи

Использование «this» в литерале объекта

важность: 5

Здесь функция makeUser возвращает объект.

Каким будет результат при обращении к свойству объекта ref ? Почему?

function makeUser() < return < name: "John", ref: this >; > let user = makeUser(); alert( user.ref.name ); // Каким будет результат?

Ответ: ошибка.

function makeUser() < return < name: "John", ref: this >; > let user = makeUser(); alert( user.ref.name ); // Error: Cannot read property 'name' of undefined

Это потому, что правила, которые определяют значение this , никак не смотрят на объявление объекта. Важен лишь момент вызова.

Здесь значение this внутри makeUser() равно undefined , потому что оно вызывается как функция, а не через «точечный» синтаксис как метод.

Значение this одно для всей функции, блоки кода и объектные литералы на него не влияют.

Таким образом, ref: this фактически принимает текущее this функции makeUser() .

Мы можем переписать функцию и вернуть то же самое this со значением undefined :

function makeUser() < return this; // на этот раз нет литерала объекта >alert( makeUser().name ); // Error: Cannot read property 'name' of undefined

Как вы можете видеть, результат alert( makeUser().name ) совпадает с результатом alert( user.ref.name ) из предыдущего примера.

Вот противоположный случай:

function makeUser() < return < name: "John", ref() < return this; >>; > let user = makeUser(); alert( user.ref().name ); // John

Теперь это работает, поскольку user.ref() – это метод. И значением this становится объект перед точкой . .

Определение методов

Начиная с ECMAScript 6, существует короткий синтаксис для определения методов в инициализаторе объекта. По сути, это сокращение для функции, которая назначена имени метода.

Синтаксис

var obj = < property([parameters]) <>, get property() <>, set property(value) <>, * generator() <> >;

Описание

Короткий синтаксис похожий на синтаксис getter’ов и setter’ов представленных в ECMAScript 5.

var obj =  foo: function () >, bar: function () >, >; 

Вы теперь можете сократить до:

var obj =  foo() >, bar() >, >; 

Сокращение методов-генераторов

Методы-генераторы также могут быть определены используя короткий синтаксис. Обратите внимание, что звёздочка (*) в коротком синтаксисе должна быть перед именем свойства генератора. То есть, * g()<> будет работать, а g *()<> не будет.

// Используя свойство с именем (pre-ES6) var obj2 =  g: function* ()  var index = 0; while (true) yield index++; >, >; // Тот же объект используя короткий синтаксис var obj2 =  *g()  var index = 0; while (true) yield index++; >, >; var it = obj2.g(); console.log(it.next().value); // 0 console.log(it.next().value); // 1 

Определения методов (ES6) не могут быть конструкторами

Все определения методов кроме методов-генераторов не могут быть конструкторами и будут выбрасывать TypeError если вы попытаетесь создать их экземпляр.

var obj =  method() >, >; new obj.method(); // TypeError: obj.method is not a constructor var obj =  *g() >, >; new obj.g(); // Генератор 

Примеры

Простой тестовый пример

var obj =  a: "foo", b()  return this.a; >, >; console.log(obj.b()); // "foo" 

Вычисляемые имена свойств

Короткий синтаксис также поддерживает вычисляемые имена свойств.

var bar =  foo0: function ()  return 0; >, foo1()  return 1; >, ["foo" + 2]()  return 2; >, >; console.log(bar.foo0()); // 0 console.log(bar.foo1()); // 1 console.log(bar.foo2()); // 2 

Спецификации

Specification
ECMAScript Language Specification
# sec-method-definitions

Совместимость с браузерами

BCD tables only load in the browser

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *