Методы объектов 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; >;
Что такое метод в javascript
Для опосредования доступа к свойствам класса в последних стандартах JavaScript была добавлена поддержка методов доступа — get и set . Сначала рассмотрим проблему, с которой мы можем столкнуться:
class Person < constructor(name, age)< this.name = name; this.age = age; >> const tom = new Person("Tom", 37); console.log(tom.age); // 37 tom.age = -15; console.log(tom.age); // -15
Класс Person определяет два свойства — name (имя) и age (возраст человека), значения которых мы можем получить или установить. Но что если мы передадим некорректные значения? Так, в примере выше свойству age передается отрицательное число, но возраст не может быть отрицательным.
Чтобы выйти из этой ситуации, мы можем определить приватное поле age , к которому можно было бы обратиться только из текущего класса. А для получения или установки его значения создать специальные методы:
class Person < #ageValue = 1; constructor(name, age)< this.name = name; this.setAge(age); >getAge() < return this.#ageValue; >setAge(value)< if(value>0 && value < 110) this.#ageValue = value; >> const tom = new Person("Tom", 37); console.log(tom.getAge()); // 37 tom.setAge(-15); console.log(tom.getAge()); // 37
Теперь возраст хранится в приватном поле ageValue . При его установке в методе setAge() проверяется переданное значение. И установка происходит, если только передано корректное значение. А метод getAge() возвращает значение этой переменной.
Но есть и другое решение — применение методов доступа get и set .
// определение приватного поля #field; set field(value) < this.#field= value; >get field()
Оба метода — get и set имеют одинаковые названия. Как правило, они опосредуют доступ к некоторому приватному полю. Метод set предназначен для установки. Он принимает в качестве параметра новое значение. Далее в методе set мы можем выполнить ряд действий при установке.
Метод get предназначен для получения значения. Здесь мы можем определить какую-нибудь логику при возвращении значения.
Так, перепишем предыдущий пример с использованием get и set :
class Person < #ageValue = 1; constructor(name, age)< this.name = name; this.age = age; >set age(value)< console.log(`Передано $`); if(value>0 && value < 110) this.#ageValue = value; >get age() < return this.#ageValue; >> const tom = new Person("Tom", 37); console.log(tom.age); tom.age = -15; console.log(tom.age);
Стоит отметить, что работа с методами доступа производится также, как с обычными свойствами. Так, для получения значения и вывода на консоль применяется вызов:
console.log(tom.age);
console.log(tom.age());
То есть при обращении tom.age фактически будет срабатывать метод get , который возвратит значение поля ageValue .
tom.age = -15;
будет срабатывать метод set , который получит передаваемое ему значение (здесь число -15) через единственный параметр. И далее в самом методе set мы можем решить, надо ли устанавливать это значение.
Свойства, доступные только для чтения
Выше применялись оба метода get и set , соответственно значение поля можно было и получить, и установить. Однако в реальност мы можем использовать только один из них. Например, мы можем оставить только метод get и тем самым сделать свойство доступным только для чтения .
Например, в изменим пример выше и сделаем свойство name доступным только для чтения:
class Person < #age = 1; #name; constructor(name, age)< this.#name = name; this.age = age; >//set name(value) < this.#name = value; >get name() < return this.#name; >set age(value)< if(value>0 && value < 110) this.#age = value; >get age() < return this.#age; >> const tom = new Person("Tom", 37); console.log(tom.name); // Tom tom.name = "Bob"; // Это ничего не даст console.log(tom.name); // Tom - значение не изменилось
В данном случае вместо общедоступного свойства name определена приватное поле #name . Его можно установить только из внутри класса, что мы и делаем в конструкторе класса. Однако из вне его можно только прочитать с помощью метода get . Поэтому попытка установки свойства
tom.name = "Bob";
ни к чему не приведет
Свойства только для установки
Также мы можем сделать свойство доступным только для записи, оставив только метод set . Например, добавим новое свойство id, которое будет доступно только для записи:
class Person < #id; constructor(name, age, id)< this.name = name; this.age = age; this.id = id; >set id(value) < this.#id = value;>print() < console.log(`id: $name: $ age: $`); > > const tom = new Person("Tom", 37, 1); tom.print(); // id: 1 name: Tom age: 37 tom.id = 55; // устанавливаем значение свойства id tom.print(); // id: 55 name: Tom age: 37 console.log(tom.id); // undefined - значение свойства id нельзя получить
Здесь определено свойство id , которое устанавливает значение приватного поля #id . Но поскольку метода get для этого свойства не определено, то при попытке получить значение свойства id, мы получим undefined :
console.log(tom.id); // undefined - значение свойства id нельзя получить
Свойства без обращения к полям
Стоит отметить, что методы get и set необязательно должны обращаться к приватным или неприватным полям. Это могут быть и вычисляемые свойства. Например:
class Person < constructor(firstName, lastName)< this.firstName = firstName; this.lastName = lastName; >get fullName() < return `$$` > > const tom = new Person("Tom", "Smith"); console.log(tom.fullName); // Tom Smith
В данном случае свойство для чтения fullName возращает фактически объединение двух свойств — firstName и lastName .
Подобным образом можно определить и свойство для записи:
class Person < constructor(firstName, lastName)< this.firstName = firstName; this.lastName = lastName; >get fullName() < return `$$` > set fullName(value) < [this.firstName, this.lastName] = value.split(" "); >> const tom = new Person("Tom", "Smith"); console.log(tom.fullName); // Tom Smith tom.fullName = "Tomas Jefferson"; console.log(tom.lastName); // Jefferson
В данном случае метод set свойства fullName в качестве параметра получает некоторую строку и с помощью ее метода split разбивает по пробелу и получает массив подстрок, которые были разделены пробелом. То есть, теоретически мы рассчитываем, что будет передано что-то наподобие «Tom Smith», а после разделения по пробелу свойство firstName получит значение «Tom», а свойтсво lastName — значение «Smith». Стоит отметить, что для простоты и целй демонстрации здесь мы не рассматриваем исключительные ситуации, когда передается пустая строка или строка, которая не делится по пробелу на две части и т.д.
В итоге при получении нового значения
tom.fullName = "Tomas Jefferson";
Метод set разобьет его по пробелу, и первый элемент массива будет передан свойству firstName , а второй — свойству lastName .
JavaScript Методы объекта
В определении функции this относится к функции «person».
В приведенном выше примере this является объект person, к которому «принадлежит» функция fullName.
Другими словами, this.firstName означает свойство firstName объекта this.
Подробнее о ключевом слове this читайте в Ключевое слово this.
JavaScript Методы
JavaScript Методы — это действия, которые можно выполнять над объектами.
JavaScript Метод — это свойство, содержащее определение функции.
| Свойство | Значение |
|---|---|
| firstName | Щипунов |
| lastName | Андрей |
| age | 50 |
| eyeColor | зеленый |
| fullName | function() |
Методы — это функции, хранящиеся в виде свойств объекта.
Доступ к методам объекта
Вы получаете доступ к методу объекта со следующим синтаксисом:
objectName.methodName()
Обычно вы описываете fullName() как метод объекта person, а fullName как свойство.
Свойство fullName будет выполняться (как функция), когда она вызывается с помощью круглых скобок ().
В этом примере осуществляется доступ к функции fullName() метода объекта person:
Пример
name = person.fullName();
Если вы получите доступ к свойству fullName, без (), оно вернёт определение функции:
Пример
name = person.fullName;
Использование встроенных методов
В этом примере используется метод toUpperCase() объекта String для преобразования текста в верхний регистр:
var message = «Привет мир!»;
var x = message.toUpperCase();
Значение x после выполнения приведенного выше кода будет:
ПРИВЕТ МИР!
Добавление метода к объекту
Добавить новый метод к объекту очень просто:
JavaScript: Методы
Кроме свойств, у данных существуют методы — функции, находящиеся внутри свойств. С практической точки зрения это значит, что метод работает и вызывается как функция, но делает это как свойство, через точку.
const name = 'Robb'; const upperName = name.toUpperCase(); console.log(upperName); // => ROBB
Встроенные методы всегда оперируют теми данными, с которыми они связаны. Метод .toUpperCase() возвращает ту же строку, но преобразуя все символы в верхний регистр. Методов у данных обычно значительно больше, чем свойств, например, для строк их несколько десятков. В документации, на первый взгляд, они описаны немного странно: String.prototype.toLowerCase(). Это описание раскрывает некоторые внутренние детали реализации, которые сейчас не важны, да и мы не изучили всей необходимой базы для разговора о прототипах.
Методы есть и у чисел:
const temperature = 22.93; // Округление до одного знака после запятой const roundedTemperature = temperature.toFixed(1); // Метод возвращает строку, которая содержит преобразованное число console.log(roundedTemperature); // => 22.9 // Напрямую можно вызывать так // Скобки нужны обязательно, иначе не заработает (22.93).toFixed(1); // 22.9
Хозяйке на заметку. Технически всё несколько сложнее. Методы есть не у самих чисел, а у данных (объектов) типа Number. Числа, записанные в переменные или константы, автоматически преобразуются к данному типу во время обращения к ним, в это время происходит так называемый boxing.
Возникает закономерный вопрос: зачем нужны методы, почему не просто функции? С числами ситуация ещё сложнее. Часть операций реализована в виде методов самих чисел, например, .toFixed() , а ещё большая часть — в виде методов, доступных через Math .
Есть две причины почему так сделано:
- Исторически так сложилось. JavaScript разрабатывался слишком быстро и поэтому не все было продумано хорошо
- Далеко не все функции имеют отношение к конкретному значению. Возьмем для примера Math.min() . Эта функция находит минимальное число среди всех, которые ему были переданы. Эту функцию нелогично делать методом конкретного числа, например, так — (1).min() . Она не имеет никакой связи с конкретным числом
С другой стороны, функции, работающие с конкретным числом, для единообразия должны быть реализованы как методы. К таким функциям относится получение модуля числа. То есть вместо такого вызова Math.abs(-10) , логично иметь такой: (-10).abs() .
Что касается методов в целом, то не все так однозначно. Есть языки, в которых методов нет и там всё прекрасно, есть языки, где методы — это основной способ работы с функциями, но даже в этих языках всегда, наряду с методами, используются обычные функции. JavaScript — язык, в котором прижились оба подхода, в нём активно используются как обычные функции, так и методы. О плюсах и минусах подобных подходов подробно рассказывается в курсах посвященных ООП.
Задание
Приведите строку text к нижнему регистру и напечатайте её на экран.
Упражнение не проходит проверку — что делать?
Если вы зашли в тупик, то самое время задать вопрос в «Обсуждениях». Как правильно задать вопрос:
- Обязательно приложите вывод тестов, без него практически невозможно понять что не так, даже если вы покажете свой код. Программисты плохо исполняют код в голове, но по полученной ошибке почти всегда понятно, куда смотреть.
В моей среде код работает, а здесь нет
Тесты устроены таким образом, что они проверяют решение разными способами и на разных данных. Часто решение работает с одними входными данными, но не работает с другими. Чтобы разобраться с этим моментом, изучите вкладку «Тесты» и внимательно посмотрите на вывод ошибок, в котором есть подсказки.
Мой код отличается от решения учителя
Это нормально , в программировании одну задачу можно выполнить множеством способов. Если ваш код прошел проверку, то он соответствует условиям задачи.
В редких случаях бывает, что решение подогнано под тесты, но это видно сразу.
Прочитал урок — ничего не понятно
Создавать обучающие материалы, понятные для всех без исключения, довольно сложно. Мы очень стараемся, но всегда есть что улучшать. Если вы встретили материал, который вам непонятен, опишите проблему в «Обсуждениях». Идеально, если вы сформулируете непонятные моменты в виде вопросов. Обычно нам нужно несколько дней для внесения правок.
Кстати, вы тоже можете участвовать в улучшении курсов: внизу есть ссылка на исходный код уроков, который можно править прямо из браузера.