Как найти значение свойства объекта

Есть объект с героями.У каждого героя есть ключ movies — это массив с фильмами, где участвовал данный герой. Мне необходимо найти всех героев, у которых в movies есть значение «Thor». Как это можно реализовать?
введите сюда описание изображения

введите сюда описание изображения

  • javascript
  • массивы
  • объекты
  • filter

задан 16 июл 2020 в 13:54

twinpig's user avatar

4

  • Язык программирования то хоть какой?

    16 июл 2020 в 14:09

  • Язык JavaScript

    16 июл 2020 в 15:03

  • Может массив героев?

    16 июл 2020 в 15:07

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

    16 июл 2020 в 16:54

1 ответ

arr.filter(item => {
  return item.movies.includes('Thor')
})

ответ дан 16 июл 2020 в 15:09

RavenTheX's user avatar

RavenTheXRavenTheX

8899 серебряных знаков15 бронзовых знаков

0

Материал, перевод которого мы сегодня публикуем, посвящён исследованию объектов — одной из ключевых сущностей JavaScript. Он рассчитан, преимущественно, на начинающих разработчиков, которые хотят упорядочить свои знания об объектах.

Объекты в JavaScript представляют собой динамические коллекции свойств, которые, кроме того, содержат «скрытое» свойство, представляющее собой прототип объекта. Свойства объектов характеризуются ключами и значениями. Начнём разговор о JS-объектах с ключей.

Ключи свойств объектов

Ключ свойства объекта представляет собой уникальную строку. Для доступа к свойствам можно использовать два способа: обращение к ним через точку и указание ключа объекта в квадратных скобках. При обращении к свойствам через точку ключ должен представлять собой действительный JavaScript-идентификатор. Рассмотрим пример:

let obj = {
  message : "A message"
}
obj.message //"A message"
obj["message"] //"A message"

При попытке обращения к несуществующему свойству объекта сообщения об ошибке не появится, но возвращено будет значение undefined:

obj.otherProperty //undefined

При использовании для доступа к свойствам квадратных скобок можно применять ключи, которые не являются действительными JavaScript-идентификаторами (например, ключ может быть строкой, содержащей пробелы). Они могут иметь любое значение, которое можно привести к строке:

let french = {};
french["merci beaucoup"] = "thank you very much";

french["merci beaucoup"]; //"thank you very much"

Если в качестве ключей используются нестроковые значения, они автоматически преобразуются к строкам (с использованием, если это возможно, метода toString()):

et obj = {};
//Number
obj[1] = "Number 1";
obj[1] === obj["1"]; //true
//Object
let number1 = {
  toString : function() { return "1"; }
}
obj[number1] === obj["1"]; //true

В этом примере в качестве ключа используется объект number1. Он, при попытке доступа к свойству, преобразуется к строке 1, а результат этого преобразования используется как ключ.

Значения свойств объектов

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

▍Объект как значение свойства объекта

Объекты можно помещать в другие объекты. Рассмотрим пример:

let book = {
  title : "The Good Parts",
  author : {
    firstName : "Douglas",
    lastName : "Crockford"
  }
}
book.author.firstName; //"Douglas"

Подобный подход можно использовать для создания пространств имён:

let app = {};
app.authorService = { getAuthors : function() {} };
app.bookService = { getBooks : function() {} };

▍Функция как значение свойства объекта

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

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

Динамическая природа объектов

Объекты в JavaScript, по своей природе, являются динамическими сущностями. Добавлять в них свойства можно в любое время, то же самое касается и удаления свойств:

let obj = {};
obj.message = "This is a message"; //добавление нового свойства
obj.otherMessage = "A new message"; // добавление нового свойства
delete obj.otherMessage; //удаление свойства

Объекты как ассоциативные массивы

Объекты можно рассматривать как ассоциативные массивы. Ключи ассоциативного массива представляют собой имена свойств объекта. Для того чтобы получить доступ к ключу, все свойства просматривать не нужно, то есть операция доступа к ключу ассоциативного массива, основанного на объекте, выполняется за время O(1).

Прототипы объектов

У объектов есть «скрытая» ссылка, __proto__, указывающая на объект-прототип, от которого объект наследует свойства.

Например, объект, созданный с помощью объектного литерала, имеет ссылку на Object.prototype:

var obj = {};
obj.__proto__ === Object.prototype; //true

▍Пустые объекты

Как мы только что видели, «пустой» объект, {}, на самом деле, не такой уж и пустой, так как он содержит ссылку на Object.prototype. Для того чтобы создать по-настоящему пустой объект, нужно воспользоваться следующей конструкцией:

Object.create(null)

Благодаря этому будет создан объект без прототипа. Такие объекты обычно используют для создания ассоциативных массивов.

▍Цепочка прототипов

У объектов-прототипов могут быть собственные прототипы. Если попытаться обратиться к свойству объекта, которого в нём нет, JavaScript попытается найти это свойство в прототипе этого объекта, а если и там нужного свойства не окажется, будет сделана попытка найти его в прототипе прототипа. Это будет продолжаться до тех пор, пока нужное свойство не будет найдено, или до тех пор, пока не будет достигнут конец цепочки прототипов.

Значения примитивных типов и объектные обёртки

JavaScript позволяет работать со значениями примитивных типов как с объектами, в том смысле, что язык позволяет обращаться к их свойствам и методам.

(1.23).toFixed(1); //"1.2"
"text".toUpperCase(); //"TEXT"
true.toString(); //"true"

При этом, конечно, значения примитивных типов объектами не являются.

Для организации доступа к «свойствам» значений примитивных типов JavaScript, при необходимости, создаёт объекты-обёртки, которые, после того, как они оказываются ненужными, уничтожаются. Процесс создания и уничтожения объектов-обёрток оптимизируется JS-движком.

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

Встроенные прототипы

Объекты-числа наследуют свойства и методы от прототипа Number.prototype, который является наследником Object.prototype:

var no = 1;
no.__proto__ === Number.prototype; //true
no.__proto__.__proto__ === Object.prototype; //true

Прототипом объектов-строк является String.prototype. Прототипом объектов-логических значений является Boolean.prototype. Прототипом массивов (которые тоже являются объектами), является Array.prototype.

Функции в JavaScript тоже являются объектами, имеющими прототип Function.prototype. У функций есть методы наподобие bind(), apply() и call().

Все объекты, функции, и объекты, представляющие значения примитивных типов (за исключением значений null и undefined) наследуют свойства и методы от Object.prototype. Это ведёт к тому, что, например, у всех них есть метод toString().

Расширение встроенных объектов с помощью полифиллов

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

▍Использование полифиллов

Например, существует полифилл для метода Object.assign(). Он позволяет добавить в Object новую функцию в том случае, если она в нём недоступна.

То же самое относится и к полифиллу Array.from(), который, в том случае, если в объекте Array нет метода from(), оснащает его этим методом.

▍Полифиллы и прототипы

С помощью полифиллов новые методы можно добавлять к прототипам объектов. Например, полифилл для String.prototype.trim() позволяет оснастить все строковые объекты методом trim():

let text = "   A text  ";
text.trim(); //"A text"

Полифилл для Array.prototype.find() позволяет оснастить все массивы методом find(). Похожим образом работает и полифилл для Array.prototype.findIndex():

let arr = ["A", "B", "C", "D", "E"];
arr.indexOf("C"); //2

Одиночное наследование

Команда Object.create() позволяет создавать новые объекты с заданным объектом-прототипом. Эта команда используется в JavaScript для реализации механизма одиночного наследования. Рассмотрим пример:

let bookPrototype = {
  getFullTitle : function(){
    return this.title + " by " + this.author;
  }
}
let book = Object.create(bookPrototype);
book.title = "JavaScript: The Good Parts";
book.author = "Douglas Crockford";
book.getFullTitle();//JavaScript: The Good Parts by Douglas Crockford

Множественное наследование

Команда Object.assign() копирует свойства из одного или большего количества объектов в целевой объект. Её можно использовать для реализации схемы множественного наследования. Вот пример:

let authorDataService = { getAuthors : function() {} };
let bookDataService = { getBooks : function() {} };
let userDataService = { getUsers : function() {} };
let dataService = Object.assign({},
 authorDataService,
 bookDataService,
 userDataService
);
dataService.getAuthors();
dataService.getBooks();
dataService.getUsers();

Иммутабельные объекты

Команда Object.freeze() позволяет «заморозить» объект. В такой объект нельзя добавлять новые свойства. Свойства нельзя удалять, нельзя и изменять их значения. Благодаря использованию этой команды объект становится неизменяемым или иммутабельным:

"use strict";
let book = Object.freeze({
  title : "Functional-Light JavaScript",
  author : "Kyle Simpson"
});
book.title = "Other title";//Ошибка: Cannot assign to read only property 'title'

Команда Object.freeze() выполняет так называемое «неглубокое замораживание» объектов. Это означает, что объекты, вложенные в «замороженный» объект, можно изменять. Для того чтобы осуществить «глубокую заморозку» объекта, нужно рекурсивно «заморозить» все его свойства.

Клонирование объектов

Для создания клонов (копий) объектов можно использовать команду Object.assign():

let book = Object.freeze({
  title : "JavaScript Allongé",
  author : "Reginald Braithwaite"
});
let clone = Object.assign({}, book);

Эта команда выполняет неглубокое копирование объектов, то есть — копирует только свойства верхнего уровня. Вложенные объекты оказываются, для объектов-оригиналов и их копий, общими.

Объектный литерал

Объектные литералы дают разработчику простой и понятный способ создания объектов:

let timer = {
  fn : null,
  start : function(callback) { this.fn = callback; },
  stop : function() {},
}

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

timer.fn;//null 
timer.start = function() { console.log("New implementation"); }

Метод Object.create()

Решить две вышеозначенные проблемы можно благодаря совместному использованию методов Object.create() и Object.freeze().

Применим эту методику к нашему предыдущему примеру. Сначала создадим замороженный прототип timerPrototype, содержащий в себе все методы, необходимые различным экземплярам объекта. После этого создадим объект, являющийся наследником timerPrototype:

let timerPrototype = Object.freeze({
  start : function() {},
  stop : function() {}
});
let timer = Object.create(timerPrototype);
timer.__proto__ === timerPrototype; //true

Если прототип защищён от изменений, объект, являющийся его наследником, не сможет изменять свойства, определённые в прототипе. Теперь методы start() и stop() переопределить нельзя:

"use strict";
timer.start = function() { console.log("New implementation"); } //Ошибка: Cannot assign to read only property 'start' of object

Конструкцию Object.create(timerPrototype) можно использовать для создания множества объектов с одним и тем же прототипом.

Функция-конструктор

В JavaScript существуют так называемые функции-конструкторы, представляющие собой «синтаксический сахар» для выполнения вышеописанных действий по созданию новых объектов. Рассмотрим пример:

function Timer(callback){
  this.fn = callback;
}
Timer.prototype = {
  start : function() {},
  stop : function() {}
}
function getTodos() {}
let timer = new Timer(getTodos);

В качестве конструктора можно использовать любую функцию. Конструктор вызывают с использованием ключевого слова new. Объект, созданный с помощью функции-конструктора с именем FunctionConstructor, получит прототип FunctionConstructor.prototype:

let timer = new Timer();
timer.__proto__ === Timer.prototype;

Тут, для предотвращения изменения прототипа, опять же, можно прототип «заморозить»:

Timer.prototype = Object.freeze({
  start : function() {},
  stop : function() {}
});

▍Ключевое слово new

Когда выполняется команда вида new Timer(), производятся те же действия, которые выполняет представленная ниже функция newTimer():

function newTimer(){
  let newObj = Object.create(Timer.prototype);
  let returnObj = Timer.call(newObj, arguments);
  if(returnObj) return returnObj;
    
  return newObj;
}

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

Ключевое слово class

В ECMAScript 2015 появился новый способ выполнения вышеописанных действий, представляющий собой очередную порцию «синтаксического сахара». Речь идёт о ключевом слове class и о соответствующих конструкциях, связанных с ним. Рассмотрим пример:

class Timer{
  constructor(callback){
    this.fn = callback;
  }
  
  start() {}
  stop() {}  
}
Object.freeze(Timer.prototype);

Объект, созданный с использованием ключевого слова class на основе класса с именем ClassName, будет иметь прототип ClassName.prototype. При создании объекта на основе класса нужно использовать ключевое слово new:

let timer= new Timer();
timer.__proto__ === Timer.prototype;

Использование классов не делает прототипы неизменными. Их, если это нужно, придётся «замораживать» так же, как мы это уже делали:

Object.freeze(Timer.prototype);

Наследование, основанное на прототипах

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

Хорошо было бы, если бы функции-конструкторы и классы могли бы автоматически делать прототипы неизменными.

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

▍Проблема отсутствия встроенных механизмов инкапсуляции

В шаблоне прототипного наследования не используется разделение свойств объектов на приватные и общедоступные. Все свойства объектов являются общедоступными.

Например, команда Object.keys() возвращает массив, содержащий все ключи свойств объекта. Его можно использовать для перебора всех свойств объекта:

function logProperty(name){
  console.log(name); //имя свойства
  console.log(obj[name]); //значение свойства
}
Object.keys(obj).forEach(logProperty);

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

class Timer{
  constructor(callback){
    this._fn = callback;
    this._timerId = 0;
  }
}

Фабричные функции

Инкапсулированные объекты в JavaScript можно создавать с использованием фабричных функций. Выглядит это так:

function TodoStore(callback){
    let fn = callback;
    
    function start() {},
    function stop() {}
    
    return Object.freeze({
       start,
       stop
    });
}

Здесь переменная fn является приватной. Общедоступными являются лишь методы start() и stop(). Эти методы нельзя модифицировать извне. Здесь не используется ключевое слово this, поэтому при использовании данного метода создания объектов проблема потеря контекста this оказывается неактуальной.

В команде return используется объектный литерал, содержащий лишь функции. Более того, эти функции объявлены в замыкании, они совместно пользуются общим состоянием. Для «заморозки» общедоступного API объекта используется уже известная вам команда Object.freeze().

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

Итоги

В JavaScript значения примитивных типов, обычные объекты и функции воспринимаются как объекты. Объекты имеют динамическую природу, их можно использовать как ассоциативные массивы. Объекты являются наследниками других объектов. Функции-конструкторы и классы — это «синтаксический сахар», они позволяют создавать объекты, основанные на прототипах. Для организации одиночного наследования можно использовать метод Object.create(), для организации множественного наследования — метод Object.assign(). Для создания инкапсулированных объектов можно использовать фабричные функции.

Уважаемые читатели! Если вы пришли в JavaScript из других языков, просим рассказать нам о том, что вам нравится или не нравится в JS-объектах, в сравнении с реализацией объектов в уже известных вам языках.

Перевод статьи 3 Ways To Access Object Properties in JavaScript.

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

Получить доступ к свойствам объекта в JavaScript возможно с использованием следующих трех методов доступа:

  1. С использованием точки (точечная нотация): object.property;
  2. С использованием квадратных скобок: object['property'];
  3. Деструктуризация объекта (деструктурирующее присваивание): const { property } = object.

Далее в статье мы подробно рассмотрим, как работает каждый из этих типов синтаксиса доступа к свойствам объекта. А также разберемся как и когда , в зависимости от конкретной ситуации, целесообразно их использовать на практике.

Содержание

  • 1. Метод доступа с использованием точки
      • 1.1 Метод доступа с использованием точки требует использования корректных идентификаторов
    • 2. Метод доступа к свойствам объекта, использующий квадратные скобки
    • 3. Деструктуризация объекта
      • 3.1 Используем псевдоним переменной для деструктуризации
      • 3.2 Динамическое имя свойства
    • 4. Случай когда свойство объекта не существует
    • 5. Вывод

1. Метод доступа с использованием точки

Самым распространенным способом доступа к свойству объекта является синтаксис метода доступа к свойству с использованием точки:

expression.identifier

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

Например, давайте получим доступ к свойству name объекта hero:

const hero = {
  name: 'Batman'
};

// Доступ к значению свойства с использованием точки
hero.name; // => 'Batman'

Таким образом, hero.name — это метод доступа к свойству с использованием точки, который в нашем случае получает значение свойства name объекта hero.

Для доступа к свойствам, находящимся на более глубоком уровне вложенности можно использовать это метод по цепочке: object.prop1.prop2.

Используйте метод доступа к свойству с синтаксисом точки, в том случае если вам заранее известно имя свойства . Для свойств, имена которых состоят из нескольких слов, доступ к их значению «через точку» не работает.

1.1 Метод доступа с использованием точки требует использования корректных идентификаторов

Так метод доступа к свойствам, использующий точку работает правильно, если имя свойства объекта является допустимым идентификатором. Так корректный идентификатор в языке JavaScript может содержать символы Unicode, $, _ и цифры 0..9, но не может начинаться с цифры.

Обычно это не является проблемой, потому что на практике мы в качестве имен свойств чаще всего используем корректные идентификаторы, например, name, address, street, createdBy (название, адрес, улица, создан).

Но иногда подобранные по этому принципу названия свойств не будут корректными как идентификаторы:

const weirdObject = {
  'prop-3': 'three',
  '3': 'three'
};

console.log(weirdObject.prop-3); // => NaN    
console.log(weirdObject.3); // исключение: SyntaxError: Unexpected number

Поскольку prop-3 и 3 не являются допустимыми идентификаторами, то наш метод доступа к свойству с использованием точечной нотации не работает:

  • значение свойства weirdObject.prop-3 определяется как NaN вместо ожидаемого ‘tree’;
  • weirdObject.3 приводит к возбуждению исключения SyntaxError (ошибка синтаксиса).

Подумайте, почему результат выполнения выражения weirdObject.prop-3 равен NaN? Пожалуйста, напишите свой ответ в комментарии ниже!

Тем не менее для получения доступа к значениям свойств, имена которых представляют собой некорректные идентификаторы Javascript, можно использовать такой метод, как доступ с “квадратными скобками” (его мы рассмотрим ниже):

const weirdObject = {
  'prop-3': 'three',
  '3': 'three'
};

console.log(weirdObject['prop-3']); // => 'three'
console.log(weirdObject[3]);        // => 'three' 

Используя синтаксис метода доступа, использующего квадратные скобки, мы без проблем получим значения нужных свойств и даже с такими достаточно специфическими именами: weirdObject['prop-3'] и weirdObject[3].

2. Метод доступа к свойствам объекта, использующий квадратные скобки

Метод доступа с квадратными скобками имеет следующий синтаксис:

expression1[expression2]

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

Рассмотрим следующий пример:

const property = 'name';
const hero = {
  name: 'Batman'
};

// Square brackets property accessor:
console.log(hero['name']);   // => 'Batman'
console.log(hero[property]); // => 'Batman'

Обе инструкции hero['name'] и hero[property] корректно считывают свойство name , используя синтаксис с квадратными скобками.

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

Базовый синтаксис деструктуризации объекта довольно прост:

const { identifier } = expression;

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

Рассмотрим следующий пример:

const hero = {
  name: 'Batman'
};

// Деструктуризация объекта
const { name } = hero;
console.log(name); // => 'Batman'

Инструкция const { name } = heroвыполняет деструктуризацию объекта. Деструктуризация определяет переменную name, которой передается значение свойства name объекта hero.

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

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

Обратите внимание, что вы можете извлечь значения стольких свойств, сколько захотите:

const { identifier1, identifier2, .., identifierN } = expression;

3.1 Используем псевдоним переменной для деструктуризации

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

const { identifier: aliasIdentifier } = expression;

Здесь identifier имя свойства к которому мы хотим получить доступ, aliasIdentifier имя, создаваемой переменной, а expression соответственно содержит или возвращает объект. После деструктуризации переменная aliasIdentifier будет содержать значение свойства identifier.

Рассмотрим следующий пример:

const hero = {
  name: 'Batman'
};

// Деструктуризация объекта:
const { name: heroName } = hero;
console.log(heroName); // => 'Batman'

В инструкции const { name: heroName } = hero происходит деструктуризация объекта hero. В ходе его деструктуризации определяется новая переменная heroName (вместо имени name соответствующего названию свойства, как в предыдущем примере) и присваивает heroName значение hero.name.

3.2 Динамическое имя свойства

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

const { [expression1]: identifier } = expression2;

Первое выражение expression1 возвращает имя свойства к которому мы хотим получить доступ. В identifier указывается имя переменной, создающейся после деструктуризации, в которую затем будет передано извлекаемое значение. Второе выражение expression2 должно возвращать или содержать объект, который мы хотели бы деструктурировать.

Рассмотрим следующий пример:

const property = 'name';
const hero = {
  name: 'Batman'
};

// Деструтуризация объекта:
const { [property]: name } = hero;
console.log(name); // => 'Batman'

Так в инструкции const {[property]: name} = hero мы деструктурируем объект hero и далее динамически, во время выполнения кода, определяем название его свойства, которое нам необходимо извлечь.

4. Случай когда свойство объекта не существует

Если свойство объекта, к значению которого нам необходимо получить доступ, не существует, то все три, рассмотренных нами выше, синтаксиса методов доступа будут возвращать значение undefined:

const hero = {
  characterName: 'Batman'
};

console.log(hero.name);    // => undefined
console.log(hero['name']); // => undefined
const { name } = hero;
console.log(name);         // => undefined

Свойства name не существует в объекте hero. Поэтому результатом использования методов доступа с точечной нотацией hero.name, квадратными скобками hero ['name'], а также содержимым переменной name после деструктуризации будет значение undefined .

5. Вывод

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

Синтаксис доступа к свойствам объекта с использованием точки object.property прекрасно работает, когда вам заранее известно название свойства property. А также для случая когда его имя представляет собой корректный идентификатор Javascript.

В случае если имя свойства определяется динамически или не является допустимым идентификатором, то лучшей альтернативой являются использование метода доступа с квадратными скобками: object [propertyName].

При деструктуризации объекта извлекается значение свойства непосредственно в создаваемую переменную: {property} = object. Кроме того, вы можете извлечь динамические имена свойств объекта (то есть определяемые во время выполнения кода): {[PropertName]: variable} = object.

Какой метод доступа к свойствам объектов вам выбрать зависит от конкретной задачи, которую решает ваш код. Надеюсь, что представленные на ваше рассмотрение материалы этой статьи помогут вам в будущем.

Содержание

  • Объект исследования
    • Как найти определенное свойство класса в C#
    • Как получить значение свойства объекта в C#
    • Как записать значение свойства объекта в C#
  • Итого

уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.

При разработке программ в C# бывает необходимым определить имеется ли у экземпляра класса определенное свойство, проверить или записать его значение. Для выполнения этих и других операций мы можем воспользоваться классом из System.Reflection PropertyInfo. Этот класс предоставляет подробную информацию о свойстве класса или объекта.

Объект исследования

Допишем наш класс Person, используемый в прошлой статье, следующим образом:

class Account
 { 
     public string Login { get; set; }
     public string Password { get; set; } 
 }

 class Person
 {
     public Person()
     {
         Account = new Account();
     }
     public Person(string name, string family, byte age):this()
     {
         Name = name;
         Family = family;
         Age = age;
     }
     public string Name { get; set; }
     public string Family { get; set; }
     private byte age;
     public byte Age 
     {
         get 
         {
             return age;
         }
         set
         { if (value > 100)
                 throw new Exception("Возраст человека не может быть больше 100 лет");
             else
                 age = value;
                     
         }
     }
     public Account Account { get; private set; }
 }

Как можно увидеть, у нашего класса определено свойство Account, которое представляет собой т.н. вложенный тип.

Как найти определенное свойство класса в C#

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

Person user = new Person("Вася", "Пупкин", 18);
user.Account.Login = "Uasya";
user.Account.Password = "password";

Type type = user.GetType();
PropertyInfo property = type.GetProperty("AcCoUnt", BindingFlags.IgnoreCase | BindingFlags.Instance| BindingFlags.Public);
if (property != null)
    Console.WriteLine("Свойство найдено");
else
    Console.WriteLine("Свойство не найдено");

Здесь следует обратить внимание на выставленные флаги BindingFlags. Используя связку BindingFlags.IgnoreCase | BindingFlags.Instance| BindingFlags.Public, мы пробуем найти публичное свойство, игнорируя регистр букв в имени. Поэтому результатом выполнения этого кода будет следующая строка:

Если свойство обнаружено, то, используя методы и свойства класса PropertyInfo мы можем его детально исследовать:

Person user = new Person("Вася", "Пупкин", 18);
user.Account.Login = "Uasya";
user.Account.Password = "password";

Type type = user.GetType();
PropertyInfo property = type.GetProperty("AcCoUnt", BindingFlags.IgnoreCase | BindingFlags.Instance| BindingFlags.Public);
if (property != null)
{
    Console.WriteLine("Свойство найдено");
    Console.WriteLine($"Тип свойства: {property.PropertyType}");
    Console.WriteLine($"Доступно для чтения: {property.CanRead}");
    Console.WriteLine($"Доступно для записи: {property.CanWrite}");
    bool isClass = property.PropertyType.IsClass;
    Console.WriteLine($"Свойство является классом: {isClass}");
    if (isClass)
    {
        Console.WriteLine($"Перечисляем свойства класса {property.PropertyType.Name}");
        foreach (PropertyInfo info in property.PropertyType.GetProperties())
        {
            Console.WriteLine($"    {info.PropertyType.Name} {info.Name}");
        }
    }
}    
else
    Console.WriteLine("Свойство не найдено");

Результат работы:

Свойство найдено
Тип свойства: Reflection.Account
Доступно для чтения: True
Доступно для записи: True
Свойство является классом: True
Перечисляем свойства класса Account
String Login
String Password

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

Как получить значение свойства объекта в C#

Попробуем прочитать значение найденного свойства. Для этого воспользуемся методом GetValue() у PropertyInfo. Допишем наш пример следующим образом:

[...]
if (isClass)
{
    Console.WriteLine($"Перечисляем свойства класса {property.PropertyType.Name}");
    foreach (PropertyInfo info in property.PropertyType.GetProperties())
    {
        Console.WriteLine($"    {info.PropertyType.Name} {info.Name} Значение свойства: {info.GetValue(property.GetValue(user))}");
    }
}
[...]

Результат выполнения программы:

Свойство найдено
Тип свойства: Reflection.Account
Доступно для чтения: True
Доступно для записи: True
Свойство является классом: True
Перечисляем свойства класса Account
String Login Значение свойства: Uasya
String Password Значение свойства: password

Здесь стоит обратить внимание на то, как мы получили значение свойства. Для того, чтобы получить значение свойства мы должны обязательно передать в метод экземпляр (объект) исследуемого класса. В нашем случае, это объект с именем user. Таким образом, вначале мы использовали метод GetValue() для того, чтобы получить объект Account из объекта user и только затем мы передали значение свойства Account в метод GetValue(), чтобы прочитать значение свойств Login и Password.

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

private static PropertyInfo GetProperty(object t, string PropertName)
{
    if (t.GetType().GetProperties().Count(p => p.Name == PropertName.Split('.')[0]) == 0)
        throw new ArgumentNullException(string.Format("Property {0}, is not exists in object {1}", PropertName, t.ToString()));
    if (PropertName.Split('.').Length == 1)
        return t.GetType().GetProperty(PropertName);
    else
        return GetProperty(t.GetType().GetProperty(PropertName.Split('.')[0]).GetValue(t, null), PropertName.Split('.')[1]);
}

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

PropertyInfo property = GetProperty(user, "Account.Login");

В данном случае, мы пробуем получить информацию о свойстве Login, которое относится к объекту Account, который, в свою очередь является свойством объекта user.

Как записать значение свойства объекта в C#

Для записи значения свойства нам необходимо воспользоваться методом SetValue(). Например:

Person user = new Person("Вася", "Пупкин", 18);
user.Account.Login = "Uasya";
user.Account.Password = "password";

Type type = user.GetType();
PropertyInfo property = type.GetProperty("Name");
if (property != null)
{
    Console.WriteLine($"Старое значение свойства {property.GetValue(user)}");
    property.SetValue(user, "Петя");
    Console.WriteLine($"Новое значение свойства {property.GetValue(user)}");
}

Итого

Для работы со свойствами классов и объектов C# используется класс PropertyInfo. Используя экземпляры этого класса мы можем получить детальную информацию о свойстве, а также прочитать или записать его значение для определенного экземпляра класса, используя, соответственно, методы GetValue() и SetValue().

уважаемые посетители блога, если Вам понравилась, то, пожалуйста, помогите автору с лечением. Подробности тут.

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

Доступ к свойствам

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

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

Значение в правой части оператора должно быть именем свойства. При использовании оператора точка (.) справа должен находиться простой идентификатор, соответствующий имени свойства. Доступ к любому имени свойства, которое содержит невалидный JavaScript идентификатор (например, имя свойства содержит в себе пробел, тире или начинается с цифры), может быть получен с использованием квадратных скобок ([]).

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

Значение объекта может быть обновлено путем присваивания. Если свойство с таким именем уже существует в объекте, его значение заменяется:

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

Если имя свойства хранится в переменной, то единственный способ к нему обратиться – это применение оператора [] (квадратные скобки).

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

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

Методы объектов можно добавлять и удалять в любой момент, точно также как вы поступаете с обычными свойствами объектов:

Для доступа к свойствам объекта внутри метода используется ключевое слово this. Использование this позволяет ссылаться на объект, к которому принадлежит метод:

Здесь вместо this внутри функции (метода) greeting можно было бы обратиться к объекту, используя переменную person (сам объект):

Ключевое слово this

var person = {
  name: 'John',
  greeting: function() { 
    alert( 'Hello, ' + this.name + '!');
  }
// идентичная запись
greeting: function() { 
    alert( 'Hello, ' + person.name + '!');
  }

В предыдущем примере мы определили функцию внутри свойства greeting во время определения объекта person. Однако, мы можем определить сначала функцию, а затем закрепить ее за свойством person.fun. В таком случае поведение this не изменится:

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

Через ключевое слово this метод может получить доступ не только к любому свойству объекта, но и передать куда-нибудь ссылку на сам объект:

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

В этом примере объект person, не имеет собственного свойства (метода) fullName, а наследует это свойство от своего прототипа prototypeObject. Поскольку поиск свойства начался с person.fullName, то this внутри функции fullName будет ссылаться на объект person. Таким образом, если fullName вызывается как метод объекта person, то и this относится к person. Это очень важная особеность прототипного наследования JavaScript.

Удаление свойств

Оператор delete удаляет свойство из объек­та. Он удаляет свойство объекта, если оно есть. Удаление не касается свойств объектов, связанных по цепочке прототипов. Если свойство с таким же именем существует в цепочке прототипов, объект унаследует это свойство из прототипа.

Выражение delete возвращает true, если удаление свойства прошло успешно. delete вернет false только в том случае, когда свойство не было удалено (например, если свойство относится к защищенному объекту, принадлежащему браузеру). true возвращается даже в том случае, если свойство, которое вы пытаетесь удалить, не существует в объекте:

Итоги

  • Объект представляет собой набор свойств.
  • Получить значение свойства можно с помощью операторов точки (.) или квадратных скобок ([]).
  • Свойства можно добавить в объект в любой момент. Для этого следует присвоить значение с указанием имени нового свойства.
  • Метод представляет собой свойство, значением которого является функция. Для ссылки на объект, из которого вызывается метод, используется ключевое слово this.
  • Методы можно вызывать в точечной записи: имя объекта, точка и имя свойства метода, за которым следует пара круглых скобок.
  • Метод можно рассматривать как функцию, присвоенную свойству, поэтому новый метод можно добавить в любой момент.
  • Методы могут получать аргументы, как и обычные функции.
  • Если несуществующему свойству объекта присваивается значение, данное свойство добавляется в объект. Для удаления свойств используют инструкцию delete.

Задачи

  • Свойства объекта

    Почему данный код выдаёт синтаксическую ошибку?

    var cat = { 
    legs: 4
    name: "Гармония" 
    color: "Черепаховый"
    };
    
    alert( cat.name );  // SyntaxError
    

    Показать решение

    Решение:

    Чтобы исправить ошибку, нужно добавить запятую после первого и второго свойства.

  • Доступ к свойствам объекта

    Сохраните значения свойств объекта myObj в переменных x, y и z. Выведите значения переменных x, y и z через alert.

    var myObj = {
      "an entree": "hamburger",
      "my side": "veggies",
      "the drink": "water"
    };
    
    // ваш код
    

    Показать решение

  • Свойство в переменной

    1. В переменной myDog сохраните имя свойства объекта dogs: «hunter».
    2. Присвойте свойство с именем myDog и значением «Ротвейлер» объекту dogs.
    3. Выведите значение свойства, хранящегося в переменной myDog через alert.
    var dogs = {
      running: "Арабская борзая",
      hunter: "Лабрадор",
      guard: "Московская"
    }
    
    // ваш код
    

    Показать решение

    Решение:

    Если имя свойства объекта хранится в переменной (var myDog = «hunter»), то обратиться к нему можно только через квадратные скобки dogs[myDog].

  • Обновить свойство

    Поменяйте значение свойства guard c «Московская» на «Московская-сторожевая»

    var dogs = {
      running: "Арабская борзая",
      hunter: "Лабрадор",
      guard: "Московская"
    }
    
    // ваш код
    

    Показать решение

    Решение:

    Если имя свойства объекта хранится в переменной (var myDog = «hunter»), то обратиться к нему можно только через квадратные скобки dogs[myDog].

  • Добавление и удаление свойств

    Добавьте в объект dogs свойство с именем driving и значением «Сибирский хаски». Удалите свойство «guard» из dogs. Выведите вновь добавленное и удалённое свойства через alert.

    var dogs = {
      running: "Арабская борзая",
      hunter: "Лабрадор",
      guard: "Московская-сторожевая"
    }
    
    // ваш код
    

    Показать решение

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

    1. Определите никак не связанную с приведенными объектами dog_1 и dog_2 функцию testBreed, которая будет выводить породу (breed), тип (a type) и вес (the weight) собаки.
    2. Присвойте функцию testBreed свойству sayAbout для обоих объектов.
    3. Запустите функцию testBreed для каждого из объектов.
    var dog_1 = {
      breed: "Алабай",
      "a type": "собака-компаньон",
      "the weight": "50 кг"
    }
    
    var dog_2 = {
      breed: "Бультерьер",
      "a type": "бойцовская",
      "the weight": "36 кг"
    }
    
    // ваш код
    

    Показать решение

Понравилась статья? Поделить с друзьями:

Не пропустите также:

  • Как найти работу в хорватии
  • Как найти расстояние вектора в геометрии
  • Как найти человека в банду
  • Как найти телефон по названию телефона
  • Как найти объем конуса когда известна образующая

  • 0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии