Если у вас есть некоторый опыт работы с javascript, вы, вероятно, сталкивались с ситуациями, когда вы писали какую-то логику, она прямая и простая, но почему-то она не работает так, как, возможно, работала бы по вашему мнению.
Сегодня я хотел бы обсудить такие ситуации, когда я столкнулся с такими проблемами, и сбить их, посмотрев на детали.
Итак, приступим…
1. Прохождение объектов
Лично я следую правилу: Мы сохраняем только ссылку на объект в переменной. Да, мы не сохраняем никаких объектов внутри переменной (объявленной или параметризованной). Под ссылкой я имел в виду следующее: когда мы вызываем переменную, она указывает на исходный объект для выполнения операции. И когда мы пытаемся передать объект другой переменной или другой функции (в качестве параметра), мы фактически передаем ссылку на исходный объект. А это может привести к мутации.
Пример-объявление переменной-
var obj = { "name": "Prince Garg", "age": 23 }; var objCopy= obj; objCopy.age= 24; console.log(obj); // { "name": "Prince Garg", "age": 24 } -OOPS
И, переменная как параметр-
function someFunction( paramObj ) { paramObj.age= 24 } var obj = { "name": "Prince Garg", "age": 23 }; someFunction(obj); console.log(obj); // { "name": "Prince Garg", "age": 24 } -OOPS
Мутация может привести к катастрофе. Поэтому избегать таких ситуаций — хорошая идея. Если вы хотите передать объект из одной переменной в другую переменную или в функцию, используйте Object.assign({}, obj). Это поможет вам избежать мутаций, и вам никогда не придется беспокоиться о неожиданных изменениях объекта.
Рассмотрим модифицированные примеры-
Заявленная переменная-
var obj = { "name": "Prince Garg", "age": 23 }; var objCopy= Object.assign({}, obj); objCopy.age= 24; console.log(obj); // { "name": "Prince Garg", "age": 23 } -Yeyee
И, переменная как параметр-
function someFunction( paramObj ) { paramObj.age= 24 } var obj = { "name": "Prince Garg", "age": 23 }; someFunction( Object.assign({}, obj) ); console.log(obj); // { "name": "Prince Garg", "age": 23 } -Awesome
Но что, если мы получим объект из .find() или array[index]?
Предположим, у нас есть массив объектов, и мы хотим сохранить один из его объектов внутри переменной. Мы можем использовать .find()илиarray[index]непосредственно, чтобы получить объект и сохранить его внутри переменной. Но знаете что, это снова ссылка на объект, который будет храниться в этой переменной. И если вы измените что-либо с помощью этой переменной, которая содержит объект, он изменит исходный объект. Снова используйте Object.assign() и просто избавьтесь от неожиданной мутации.
2. Использование логических операторов
Хорошо, я знаю, вы будете кричать на меня и говорить, как, черт возьми, мир логических операторов javascript может доставить вам неприятности?
Учитывать,
var string1= "somevalue1"; var string2= "somevalue2"; var booleanTrue= true; var booleanFalse= false; var checkString= string1 && string2; // "somevalue2" var checkBoolean= booleanTrue || booleanFalse; // true if(checkString === checkBoolean) console.log("Yeyee..."); else console.log("OOPS!"); // OOPS , (WHY?)
Здесь происходит кое-что интересное. Мне нужно ваше внимание здесь, в javascript оператор «&&» возвращает последнее значение («somevalue2»), если все значения истинны, иначе ложны. И «||» оператор возвращает первое истинное значение (true). С другой стороны, «||» оператор вернет последнее ложное значение, если ни одно из значений не является истинным.
Ложными значениями являются числовой ноль (0), NaN, ложь, неопределенная и пустая строка («»). Истинные ценности — это все ценности, которые не являются ложными.
Таким образом, checkString не будет содержать логическое значение, вместо этого оно содержит истинное значение («somevalue2») в переменной checkString. А для checkBoolean? Да, как вы уже догадались, оно будет иметь значение «true». Почему? Потому что правило «||» здесь применяется оператор. Поэтому, когда мы проверяем их равенство с помощью оператора «===», мы проверяем строку («somevalue2») и логическое значение (true). Они не того типа и значения, что мы получили «Упс!» здесь.
Чтобы получить ожидаемый результат (например, «Yeyee…»), мы можем использовать Boolean( ‹expression›). Преобразует истинное значение в логическое значение true, а ложное значение — в логическое false. Или мы также можем использовать оператор not( ! ) дважды, чтобы получить логическое значение. Я предпочитаю использовать функцию Boolean(), она делает наш код более читабельным.
Учитывать,
var string1= "somevalue1"; var string2= "somevalue2"; var booleanTrue= true; var booleanFalse= false; var checkString= Boolean( string1 && string2 ); // true var checkBoolean= booleanTrue || booleanFalse; // true if(checkString === checkBoolean) console.log("Yeyee..."); else console.log("OOPS!"); // Yeyee... (We got it!)
3. Операторы «==» и «===»
«===» использует алгоритм строгого сравнения на равенство. Проще говоря, никакое принуждение не допускается. Он возвращает true только в том случае, если значения и типы равны, и false в противном случае. С другой стороны, «==» — это специальный оператор, но он также может создавать проблемы, если его неправильно понять. Он использует принуждение при преобразовании значений, если типы не совпадают, и сравнивает значения. Принуждение — обширная тема, поэтому мы сосредоточимся только на принуждении, связанном с оператором «==».
Нам нужно только понять некоторые правила, чтобы воспользоваться принудительной природой «==», и вот отличная статья, чтобы понять это.
P.S. спасибо Алексей.
Вышеприведенная таблица проста. При сравнении одинаковых типов используется тот же алгоритм, который используется для «===». При сравнении чисел со строкой строка будет преобразована в число, а затем сравнена.
Когда мы сравниваем строку с объектом, происходит нечто особенное. Каждый объект (массив, функция, объект) имеет свою собственную функцию ToPrimitive(). ToPrimitive() преобразует объект в примитивное значение (строка, логическое значение, число). Он предоставляет простое значение после преобразования сложной структуры данных для целей сравнения. Когда мы сравниваем объект с любым примитивным значением, объект вызывает ToPrimitive(), после чего выполняется сравнение.
Если вы спросите меня, когда использовать «===» и «==». Мой ответ будет-
- Сначала спросите себя, если вы уверены, что типы сравниваемых значений будут одинаковыми, то всегда используйте «===», иначе вы можете использовать «==».
- При сравнении объекта с объектом сначала преобразуйте их в строку с помощью JSON.stringify() или конкатенации с пустой строкой («»), которая будет работать нормально, а затем сравните. Ниже приведена причина этого-
Примитивы, такие как строки, логические значения и числа, сравниваются по их значению, а такие объекты, как массивы, даты и простые объекты, сравниваются по их ссылке. Это сравнение по ссылке в основном проверяет, ссылаются ли данные объекты на одно и то же место в памяти.
Вывод:
Просто помните несколько вещей при работе с Javascript, если вы хотите избежать мутаций, используйте Object.assign(). Используйте Boolean(), чтобы получить результат && и || в логическом true или false. Поймите принуждение при использовании «==», иначе вы всегда будете великолепны с «===».
Всегда помни,
ты классный