📌 Друзья, в телеграмме у нас есть отдельный чат, где вы можете задать вопрос по фронтенд-разработке и вам постараются помочь: 💬 t.me/friendlyFrontendChat Если вам это интересно, присоединяйтесь, задавайте вопросы и помогайте другим 🙂
Шикарно ложится на уже хорошую базу. Просто кайфую от понимания)) Хоть и долго к этому шел. Александр, спасибо ! Всем, кто только изучает это все - терпения и практики!
8:25 В коде рекурсия возвращает значение boolean, но потом его нужно не сразу через return возвращать ещё раз, а сделать отдельное условие: if(areValuesEqual){ continue; } else { return false; } И теперь получается когда внутренние объекты проверили и если они совпадают, то через continue переходим к следующей итерации цикла для проверки остальных ключей-значений. А если внутренние объекты не совпадают, то возвращаем false.
Да, ты прав. Где-то в комментариях ниже об этом уже была дискуссия. И в следующем видео курса про этот момент так же упомянул. Спасибо за внимательность!)
@@AleksanderLamkov Понял. Спасибо за видеоролики, помогают очень сильно заполнить пробелы, но иногда встречаются некоторые ошибки в них и новичкам может быть не особо понятно, а для тех кто уже немного программист эти баги видны и не мешают воспринимать смысл.
9:32 цикл for in на данном примере: for(const key in obj1){ obj2[key] = obj1[key] } Почему в obj2 копируется и ключ, и значение? Ведь мы указали [key], что в моем понимании переносит только значение, т.е данные именно после ' : ' Расскажу как я это вижу - сам по себе key копирует только ключ от объекта, выведя в функции for in команду console.log(key), на выходе в консоли мы получаем именно ключ(name) , но не значение, а чтобы вывести и то, и другое потребуется указать не только key, но и [key], команда console.log(key, obj1[key]) . На вашем примере мы использовали для копирования объекта только [key], т.е указали, что во 2 объект пойдут только значения, никак не ключи, но всё прекрасно работает. Почему ?
Первая часть инструкции: *obj2[key] =* obj1[key] - ищет в *obj2* свойство по имени *key* и если находит, то вторая часть инструкции: obj2[key] = *obj1[key]* - ищет в объекте *obj1* свойство по имени *key* - берёт его значение - в *obj2* обновляет значение свойства с именем *key* Если первая часть инструкции не находит в *obj2* свойства по имени *key* - в *obj2* автоматически добавится свойство с именем *key* и так же в его значение запишется то, что хранится в *obj1[key]*
ребятки, лично я долго не мог понять правильного написания синтаксиса, при использовании ключевого слова 'continue' в рекурсии...🤷🏻, хотя и понимал для чего нужна эта манипуляция. Надеюсь мой комментарий спасёт кому-то неопределённое количество нервных клеток :) код должен выглядеть следующим образом: if(areValuesObjects) { if (areObjectEqual(value1, value2)) { continue } else { return false } } то есть: если методы объекта прошли все вышеописанные проверки, то код продолжает своё выполнение, если же нет - останавливается у меня ещё совсем немного опыта в сфере frontend (-а), так что критика принимается) А я, в свою очередь, скажу автору канала большое спасибо за свежий и, действительно актуальный для трудоустройства материал 😊🤝
Спасибо за ролики! Возникло два вопроса : 1. Когда мы составляли рекурсивную функцию по поверхностному сравнению двух объектов, то вы сказали, что теперь просто сравним значения свойств обоих объектов так как в условии выше мы проверили, что ключи одинаковые. Проблема в том, что мы сравнили длину массивов с ключами, т.е. сравнили именно кол-во ключей, а потом сравнили их значения. Соответственно у меня вопрос - а название самих ключей не нужно сравнивать? Или главное, что кол-во ключей одинаковое и все. Имеется ввиду, что если у нас название свойств будет разное, то это тоже вернет true? 2. Разве в примере с await, поток не будет дожидаться выполнения функции/метода, который мы эвэйтим? Как у нас может вернуться undefined? А так, в целом, спасибо еще раз за уроки и спасибо за ответ заранее!
1. Мы ведь наоборот сравниваем, что если количество свойств в сравниваемых сущностях-объектах не совпадает, то сразу делаем вывод, что исходные объекты не идентичны. 2. Да, await будет дожидаться, здесь я ошибся, когда писал этот псевдокод.
А почему на 16:50 будет undefined, если там стоит await и renderUserName вызовется после присвоения значения в переменную userInfo? Возможно тут имеется в виду, что проверка делается для проверки, того, что данные получены такие, какие ожидаем, а не то, что сервер ещё не выполнил проверку.
Ты прав. Не должно быть await в этом примере. Я пытался показать пример, характерный для мира реакта, когда мы запрашиваем данные, записываем их в переменную data и в дальнейшем коде, в разметке, обращаемся к этим данным как к не-undefined сущности, хотя в первые доли секунд в data ничего нет.
Есть ошибка с рекурсией 8:02, так как после проверки вложенного свойства объекта уже не будет проверятся другие свойства, поскольку произойдет завершение исходной функции: if (areValuesObjects) { return areObjectsEqual(value1, value2) } Можно немного исправить: if (areValuesObjects) { if (!areObjectsEqual(value1, value2)) { return false } Благодарю за отличные видео =)
Привет! Да, ты прав. Где-то в комментариях под этим видео об этом уже писал. Там не хватает инструкции continue. Через этот способ тоже решается проблема :)
Привет! Да, ты прав, я ошибся. Спасибо за внимательность! Вместо 42-й строки внутри тела if (areValuesObjects) должно быть так: if (!areObjectsEqual(value1, value2)) { return false } else { continue } То есть мы проверяем, что если сравниваемые объекты НЕ равны, то сразу делаем вывод, что исходные объекты не эквиваленты. В ином случае - переходим к следующей итерации цикла for in с помощью ключевого слова continue.
@@AleksanderLamkov Можешь объяснить, пожалуйста, почему для подмассивов мы явно пишем continue, а для примитивов оставляем только return false? Ведь обе эти проверки внутри одного цикла for, и в случае, когда элементы не равны (примитивы или подмассивы), возвращается false и цикл завершается. Но когда проверка i-го элемента пройдена успешно, цикл for проверяет следующий элемент. Цикл же один, почему разные подходы для примитивов и сложных объектов?
Примитивы на то и примитивы, что их можно сравнить через обычный "===". А объекты (и массивы) сравнивать через "===" бесполезно, т. к. они хранят данные по ссылке. Это значит, что даже пустой объект никогда не будет равен другому абсолютно такому же по содержанию пустому объекту. Поэтому, сравнивая объекты и массивы, нужно сравнивать поочередно их внутренности, то есть рекурсивно вызывая нашу основную функцию areObjectsEqual. Ну а на счёт выражений "return" и "continue" проясню. - return всегда прерывает родительскую (и только) функцию и возвращает какой-либо результат - continue прерывает текущую итерацию цикла и цикл переходит к следующей итерации - return в рамках тела цикла прервёт И текущую итерацию цикла И всю родительскую функцию, и вернёт какой-то результат
Да, в этом уроке есть много важных тем, без понимания которых будет сложно. В этом курсе в принципе нет и не будет «лишних» тем. Я даю только то, что пригодилось лично мне за последние 2-3 года работы.
Привет Александр, я видел у вас с тартует в вк стажировка. Не хотел бы ты немного рассказать про это ? Я как понял там все строго у вас в плане информации, ни где ничего не нашел нормально. Спасибо за обучение !!!
Привет! Актуальные направления стажировок всегда можно найти на этой странице: internship.vk.company/internship Из открытых по фронту нашел только одну, к сожалению: internship.vk.company/vacancy/885
@@AleksanderLamkov закончил несколько дней назад массивы изучать, дальше объекты. Но пока в голову не залазит. Учусь в it incubatore, ну как учусь… пытаюсь.
Изучая js, массивы и их методы стали для меня бетонной стеной. По отдельности - ночью разбуди - расскажу и напишу. Вместе использовать - хрен. И это было несколько месяцев такой затуп(всем, кому js залетел и залетает с первого раза - искренне рад за вас). Шаг за шагом, из разных источников, переписывая руками, пришло понимание. Это не что-то здец сложное. Просто мозг не готов ещё уложить все по полкам. Не возвращайся к тому, от чего уходишь.
Не спорю. Факт. Кому нужен язык не для применения его во фронтенде - курсы на ютубе не подойдут, лучше сразу обращаться к первоисточнику (к спецификации).
Абсолютно бесполезная фича сравнивать объекты на идентичность, в реальности не используется нигде, и не представляю при каких условиях может пригодиться.
Первое, что приходит в голову: второй параметр функции memo из React позволяет прокинуть собственную функцию сравнения пропсов вместо встроенной shallow-функции.
@@AleksanderLamkov Если учесть на сколько неоднозначен современный JS, внутренняя структура и наследование одного и того же параметра или метода от разных уровней прототипирования от родительских объектов. Сравнивать такие вещи - бред сивой кобылы. Именно по этому скорее всего его и не сделали в нативном джаваскрипте, как это например было реализовано в jQuery через обертки.
Смотря что сравнивать. Когда мне нужно было в реакте мемоизировать компонент формы, приходилось вручную сравнивать несложные объекты пропсов вида: { … fields: { field1: 'value', field2: 'value', … } } Сравнить такое собственной функцией сравнения ну очень просто. И проблем от «прототипного наследования» в подобных ситуациях быть не может.
📌 Друзья, в телеграмме у нас есть отдельный чат, где вы можете задать вопрос по фронтенд-разработке и вам постараются помочь:
💬 t.me/friendlyFrontendChat
Если вам это интересно, присоединяйтесь, задавайте вопросы и помогайте другим 🙂
Шикарно ложится на уже хорошую базу.
Просто кайфую от понимания)) Хоть и долго к этому шел.
Александр, спасибо !
Всем, кто только изучает это все - терпения и практики!
Згоден з вами !
Cупер, уже начинаются интересные темы!!
Этот канал - золото. Спасибо!!!
просмторел 6 видео подряд и все понял. Прекрасная подача материала!
Коммент в поддержку, спасибо за урок!
Спасибо) Много нового узнал! Все очень понятно
Все круто, узнал для себе много довольно интересной инфы 🤓✌
Благодарю за классный контент!
8:25 В коде рекурсия возвращает значение boolean, но потом его нужно не сразу через return возвращать ещё раз, а сделать отдельное условие:
if(areValuesEqual){
continue;
} else {
return false;
}
И теперь получается когда внутренние объекты проверили и если они совпадают, то через continue переходим к следующей итерации цикла для проверки остальных ключей-значений.
А если внутренние объекты не совпадают, то возвращаем false.
Да, ты прав. Где-то в комментариях ниже об этом уже была дискуссия. И в следующем видео курса про этот момент так же упомянул. Спасибо за внимательность!)
@@AleksanderLamkov Понял. Спасибо за видеоролики, помогают очень сильно заполнить пробелы, но иногда встречаются некоторые ошибки в них и новичкам может быть не особо понятно, а для тех кто уже немного программист эти баги видны и не мешают воспринимать смысл.
Вы великолепный 😊
Спасибо!!! Думал, что знал об объектах все... Оказывается нет
9:32 цикл for in на данном примере:
for(const key in obj1){
obj2[key] = obj1[key]
}
Почему в obj2 копируется и ключ, и значение? Ведь мы указали [key], что в моем понимании переносит только значение, т.е данные именно после ' : '
Расскажу как я это вижу - сам по себе key копирует только ключ от объекта, выведя в функции for in команду console.log(key), на выходе в консоли мы получаем именно ключ(name) , но не значение, а чтобы вывести и то, и другое потребуется указать не только key, но и [key], команда console.log(key, obj1[key]) .
На вашем примере мы использовали для копирования объекта только [key], т.е указали, что во 2 объект пойдут только значения, никак не ключи, но всё прекрасно работает. Почему ?
Первая часть инструкции:
*obj2[key] =* obj1[key]
- ищет в *obj2* свойство по имени *key* и если находит, то вторая часть инструкции:
obj2[key] = *obj1[key]*
- ищет в объекте *obj1* свойство по имени *key*
- берёт его значение
- в *obj2* обновляет значение свойства с именем *key*
Если первая часть инструкции не находит в *obj2* свойства по имени *key* - в *obj2* автоматически добавится свойство с именем *key* и так же в его значение запишется то, что хранится в *obj1[key]*
@@AleksanderLamkov Большое спасибо !
ребятки, лично я долго не мог понять правильного написания синтаксиса, при использовании ключевого слова 'continue' в рекурсии...🤷🏻, хотя и понимал для чего нужна эта манипуляция. Надеюсь мой комментарий спасёт кому-то неопределённое количество нервных клеток :)
код должен выглядеть следующим образом:
if(areValuesObjects) {
if (areObjectEqual(value1, value2)) {
continue
} else {
return false
}
}
то есть: если методы объекта прошли все вышеописанные проверки, то код продолжает своё выполнение, если же нет - останавливается
у меня ещё совсем немного опыта в сфере frontend (-а), так что критика принимается)
А я, в свою очередь, скажу автору канала большое спасибо за свежий и, действительно актуальный для трудоустройства материал 😊🤝
Спасибо за ролики! Возникло два вопроса :
1. Когда мы составляли рекурсивную функцию по поверхностному сравнению двух объектов, то вы сказали, что теперь просто сравним значения свойств обоих объектов так как в условии выше мы проверили, что ключи одинаковые. Проблема в том, что мы сравнили длину массивов с ключами, т.е. сравнили именно кол-во ключей, а потом сравнили их значения. Соответственно у меня вопрос - а название самих ключей не нужно сравнивать? Или главное, что кол-во ключей одинаковое и все. Имеется ввиду, что если у нас название свойств будет разное, то это тоже вернет true?
2. Разве в примере с await, поток не будет дожидаться выполнения функции/метода, который мы эвэйтим? Как у нас может вернуться undefined?
А так, в целом, спасибо еще раз за уроки и спасибо за ответ заранее!
1. Мы ведь наоборот сравниваем, что если количество свойств в сравниваемых сущностях-объектах не совпадает, то сразу делаем вывод, что исходные объекты не идентичны.
2. Да, await будет дожидаться, здесь я ошибся, когда писал этот псевдокод.
А почему на 16:50 будет undefined, если там стоит await и renderUserName вызовется после присвоения значения в переменную userInfo? Возможно тут имеется в виду, что проверка делается для проверки, того, что данные получены такие, какие ожидаем, а не то, что сервер ещё не выполнил проверку.
Ты прав. Не должно быть await в этом примере.
Я пытался показать пример, характерный для мира реакта, когда мы запрашиваем данные, записываем их в переменную data и в дальнейшем коде, в разметке, обращаемся к этим данным как к не-undefined сущности, хотя в первые доли секунд в data ничего нет.
@@AleksanderLamkov Понял. Про react согласен.
Спасибо!
Выполнить глубокое копирование объекта, с вложенными объектами можно используя встроенные методы: JSON.parse(JSON.stringify(obj))
Да, старый проверенный способ.
The best
Есть ошибка с рекурсией 8:02, так как после проверки вложенного свойства объекта уже не будет проверятся другие свойства, поскольку произойдет завершение исходной функции:
if (areValuesObjects) {
return areObjectsEqual(value1, value2)
}
Можно немного исправить:
if (areValuesObjects) {
if (!areObjectsEqual(value1, value2)) {
return false
}
Благодарю за отличные видео =)
Привет! Да, ты прав. Где-то в комментариях под этим видео об этом уже писал. Там не хватает инструкции continue. Через этот способ тоже решается проблема :)
А как называется плагин для подсказок в ide?
Это не плагин. Это уже встроенный функционал в WebStorm.
8:48 return сработает слишком рано, надо возвращать только если false, потому что иначе при первом true вернёт true?
Привет! Да, ты прав, я ошибся. Спасибо за внимательность!
Вместо 42-й строки внутри тела if (areValuesObjects) должно быть так:
if (!areObjectsEqual(value1, value2)) {
return false
} else {
continue
}
То есть мы проверяем, что если сравниваемые объекты НЕ равны, то сразу делаем вывод, что исходные объекты не эквиваленты.
В ином случае - переходим к следующей итерации цикла for in с помощью ключевого слова continue.
@@AleksanderLamkov Можешь объяснить, пожалуйста, почему для подмассивов мы явно пишем continue, а для примитивов оставляем только return false? Ведь обе эти проверки внутри одного цикла for, и в случае, когда элементы не равны (примитивы или подмассивы), возвращается false и цикл завершается. Но когда проверка i-го элемента пройдена успешно, цикл for проверяет следующий элемент. Цикл же один, почему разные подходы для примитивов и сложных объектов?
Примитивы на то и примитивы, что их можно сравнить через обычный "===".
А объекты (и массивы) сравнивать через "===" бесполезно, т. к. они хранят данные по ссылке. Это значит, что даже пустой объект никогда не будет равен другому абсолютно такому же по содержанию пустому объекту.
Поэтому, сравнивая объекты и массивы, нужно сравнивать поочередно их внутренности, то есть рекурсивно вызывая нашу основную функцию areObjectsEqual.
Ну а на счёт выражений "return" и "continue" проясню.
- return всегда прерывает родительскую (и только) функцию и возвращает какой-либо результат
- continue прерывает текущую итерацию цикла и цикл переходит к следующей итерации
- return в рамках тела цикла прервёт И текущую итерацию цикла И всю родительскую функцию, и вернёт какой-то результат
@@AleksanderLamkov Понятно, спасибо!
@@AleksanderLamkov Привет, я добавил эту часть, и проверка всегда возвращает true (во вложенном объекте разные данные), можешь подсказать, где я ошибся?
const obj1 = {
name: 'Имя',
age: 30,
address: {
city: 'Moskow',
zipcode: 123456,
},
}
const obj2 = {
name: 'Имя',
age: 30,
address: {
city: 'Moskow',
zipcode: '123',
},
}
const areObjectsEqual = (object1, object2) => {
const keys1 = Object.keys(object1)
const keys2 = Object.keys(object2)
if (keys1.length !== keys2.length) {
return false
}
for (const key in object1) {
const value1 = object1[key]
const value2 = object2[key]
const areValueObjects =
typeof value1 === 'object' && typeof value2 === 'object'
if (areValueObjects) {
if (!areObjectsEqual(value1, value2)) {
return false
} else {
continue
}
}
if (value1[key] !== value2[key]) {
return false
}
}
return true
}
console.log(
`Равны ли объекты obj1 и obj2:`,
areObjectsEqual(obj1, obj2)
)
а этот урок обязательный для изучение ?
Да, в этом уроке есть много важных тем, без понимания которых будет сложно.
В этом курсе в принципе нет и не будет «лишних» тем.
Я даю только то, что пригодилось лично мне за последние 2-3 года работы.
Привет Александр, я видел у вас с тартует в вк стажировка. Не хотел бы ты немного рассказать про это ? Я как понял там все строго у вас в плане информации, ни где ничего не нашел нормально. Спасибо за обучение !!!
Привет! Актуальные направления стажировок всегда можно найти на этой странице:
internship.vk.company/internship
Из открытых по фронту нашел только одну, к сожалению:
internship.vk.company/vacancy/885
а как можно попрактиковаться на пройденном материале?
Если речь про JS темы до браузера, то посоветую задачки на codewars.
пытаюсь по немногу вникнуть , по итогу завис на ситуации
const obj1={
name:"буб",
age:25,
male:true
}
const obj2={
name:"буб",
age:25
}
const infa123 = (ob1, ob2) => {
const key1 = Object.keys(ob1)
const key2 = Object.keys(ob2)
if (key1.lenght !== key2.lenght) {
return false
}
return true;
}
console.log(infa123(obj1, obj2))
Данная штука выводит постоянно в консоль true , почему так происходит?
Имя свойства для получения длины массива неправильно написано.
length должно быть
@@AleksanderLamkov Господи , сидел над этим долгое время. Спасибо большое за ответ ! Ваше курсы чудо
structuredClone?
Да, забыл рассказать об этом способе клонирования. Спасибо!)
dude,he 28 years old and he has 30 years of experience💀
А я вот ни хрена не понимаю. Не быть мне программистом, пойду дальше коробки разгружать.
Может стоит к этому уроку вернуться позже? Дать мозгу время переварить предыдущие темы.
@@AleksanderLamkov закончил несколько дней назад массивы изучать, дальше объекты. Но пока в голову не залазит. Учусь в it incubatore, ну как учусь… пытаюсь.
Изучая js, массивы и их методы стали для меня бетонной стеной.
По отдельности - ночью разбуди - расскажу и напишу. Вместе использовать - хрен. И это было несколько месяцев такой затуп(всем, кому js залетел и залетает с первого раза - искренне рад за вас). Шаг за шагом, из разных источников, переписывая руками, пришло понимание.
Это не что-то здец сложное.
Просто мозг не готов ещё уложить все по полкам.
Не возвращайся к тому, от чего уходишь.
информация в видео - есть галюцинация автора, не имеющая оьношения к реальности описанной спецификацией языка.
Не спорю. Факт. Кому нужен язык не для применения его во фронтенде - курсы на ютубе не подойдут, лучше сразу обращаться к первоисточнику (к спецификации).
Абсолютно бесполезная фича сравнивать объекты на идентичность, в реальности не используется нигде, и не представляю при каких условиях может пригодиться.
Первое, что приходит в голову: второй параметр функции memo из React позволяет прокинуть собственную функцию сравнения пропсов вместо встроенной shallow-функции.
@@AleksanderLamkov Если учесть на сколько неоднозначен современный JS, внутренняя структура и наследование одного и того же параметра или метода от разных уровней прототипирования от родительских объектов. Сравнивать такие вещи - бред сивой кобылы.
Именно по этому скорее всего его и не сделали в нативном джаваскрипте, как это например было реализовано в jQuery через обертки.
Смотря что сравнивать. Когда мне нужно было в реакте мемоизировать компонент формы, приходилось вручную сравнивать несложные объекты пропсов вида:
{
…
fields: {
field1: 'value',
field2: 'value',
…
}
}
Сравнить такое собственной функцией сравнения ну очень просто. И проблем от «прототипного наследования» в подобных ситуациях быть не может.
Фахівці, що займаються комерційною розробкою не дуже рекомендують використовувати Рекурсію !