предисловие
Это третий раз, когда я открываю Красную книгу, которая называется «Расширенное программирование на JavaScript, 3-е издание». Я должен сказать, что, хотя книге уже несколько лет, многие знания не подходят для современной фронтенд-разработки, а для тех, для тех, кто хочет освоить JavaScript Basic для начинающих, или, как я, кто хочет восстановить те части знаний, которые были забыты в уголке памяти, эта книга все еще очень подходит, и она заслуживает того, чтобы называться «Библия JavaScript».
Эта статья предназначена для чтения.Есть еще одна причина, по которой я решил перечитать эту книгу еще раз.Раньше я делал бумажные заметки.На этот раз я хочу использовать ее в виде электронной версии,что также можно рассматривать как аранжировку предыдущих знание.
本文篇幅较长,目的是作为我的电子版学习笔记,我会尽可能去其糟粕,取其精华,同时我会添加一些书上未记载但很重要的知识点补充
let's go
Введение в JavaScript
Полный JavaScript состоит из 3 частей: ядра (синтаксис ECMAScript), DOM, BOM, последние две в настоящее время являются необязательными или могут быть абстрагированы как хост, поскольку JS больше не ограничивается запуском в браузерах.
Использование JavaScript в HTML
Использование JS в браузере можно сделать черезscript
Тег для выполнения JS-файла, который далее можно разделить на 3 способа, встроенный JS-код, указание на локальный JS-файл через src, указание на JS-файл (доменное имя) статического сервера через src, рекомендуется использовать форму src, по сравнению с Inline, может использовать кеш для повышения скорости загрузки страниц и скорости анализа DOM, а поскольку JS и HTML не связаны, он более удобен в сопровождении.
Когда тег script имеет форму srcвнешний скрипт, можно установить вdefer
,async
Атрибуты, первый позволяет запускать скрипт после парсинга страницы, второй асинхронно загружает скрипт и выполняет его, и в то же время асинхронно выполняет код JS Эти два атрибута должны решить проблему, которую браузер должен ждать пока код JS в теге script. После загрузки и выполнения следующие элементы будут проанализированы, что приведет к долгосрочной проблеме с белым экраном.
<script src="xxx" async></script>
Основные концепции JavaScript
идентификатор
Идентификаторы относятся к именам переменных, функций и свойств.Основные имена в основном это camelCase, или $,_
Первый символ не может быть числом (но разрешено начинать со второго символа)
// illegal
let 123hello = '123'
// legitimate
let $123hello = '123'
let helloWorld = '123'
let hello123World = '123'
let _$hello = '123'
тип данных
На сегодняшний день JavaScript имеет 7 простых типов данных и 1 сложный тип данных.
Простые типы данных:
- Undefined
- Null
- Boolean
- Number
- String
- Symbol
- BigInt (черновик ES10)
Сложные типы данных:
- Object
Function 是 Object 的子类,即继承于 Object
Неопределенный тип
Неопределенный тип имеет только одно значение, то есть неопределенное, его легко спутать с неопределенным, их сходства и различия очевидны.
- Использование оператора typeof возвращает 'undefined'
- Использование неопределенных переменных безопасно, использование неопределенных переменных вызовет ошибку
let foo
console.log(typeof foo) // 'undefined'
console.log(typeof bar) // 'undefined'
console.log(foo) // undefined
console.log(bar) // Uncaught ReferenceError: bar is not defined
Нулевой тип
Тип Null также имеет только одно значение, равное null.обозначает нулевой объект указатель NULL, если используется оператор typeof, возвращаемый тип — 'object', но это всего лишь языковая ошибка, исправить которую в настоящее время почти невозможно. вернет false, что доказывает, что null и Object не являются неважными
console.log(typeof null) // 'object'
console.log(null instanceof Object) // false
неопределенные значения получены из нулевых значений, поэтому они примерно равны
console.log(undefined == null) // true
Тип номера
Числовой тип JS использует формат IEEE754 для представления целых чисел и значений с плавающей запятой, что вызовет небольшие проблемы.Например, 0,1 в JS на самом деле не 0,1, его двоичное значение равно 0,001100110011..., бесконечный цикл (от малого десятичного до двоичный файл (правило умножается на 2 и округляется в большую сторону), который хранится внутри, как это
Вы можете передать функцию Number для преобразования входящих параметров в соответствующий тип Number (обратите внимание на яму неявного преобразования)
console.log(Number('123')) // 123
console.log(Number(null)) // 0
console.log(Number(undefined)) // NaN
console.log(Number('false')) // NaN
console.log(Number(true)) // 1
NaN относится к типу Number, а NaN не равен самому себе, вы можете передать объект окнаisNaN
чтобы судить, является ли параметр NaN, но у него есть недостаток, заключающийся в том, что он сначала преобразует параметр в числовой тип (также неявное преобразование), поэтому он будет отображатьсяisNaN('foo')
Возвращает true, ES6Number.isNaN
Восполняет этот недостаток, он вернет false, доказывая, что строка «foo» не является NaN.
console.log(NaN === NaN) // false
console.log(isNaN(NaN)) // true
console.log(isNaN('foo')) // true 但这是不合理的,因为 'foo' 并不是 NaN
console.log(Number.isNaN('foo')) // false
window.isNaN используется, чтобы определить, является ли параметр числом, Number.isNaN используется, чтобы определить, является ли параметр NaN
Разница между функциями parseInt и Number заключается в том, что первая анализирует аргументы посимвольно, а вторая выполняет прямое преобразование.
console.log(parseInt('123.456')) // 123
console.log(parseInt('123foo')) // 123
console.log(Number('123foo')) // NaN
parseInt будет анализировать параметр «123foo» один за другим, когда встретитнечисловые символы или десятичная точка(здесь строка f), которая вернет ранее преобразованное число, а Number преобразует весь параметр в число
(Стоит отметить, что parseFloat встречает нечисловые символы иливторойдесятичной точки, он вернет ранее преобразованное число)
String
Строки в ECMAScript однажды созданы, ихстоимостьЕго нельзя изменить.Если вам нужно изменить строку, хранящуюся в переменной, вам нужно уничтожить исходную строку и заполнить переменную другой строкой с новым значением.
Object
И DOM, и BOM-объекты являются хост-объектами, предоставляемыми хостом. Хостом здесь является браузер. Другими словами, в небраузерной среде могут отсутствовать некоторые глобальные переменные и методы в браузере. Например, в узел.
оператор
унарный оператор
Операторы, которые работают только с одним значением, называются унарными операторами.Операции постинкремента/декремента имеют важное отличие от преинкремента/декремента.Постфиксы выполняются после того, как выражение, содержащее их, было вычислено.
let num1 = 2
let num2 = 20
let num3 = --num1 + num2 // 21
let num4 = num1 + num2 // 21
let num1 = 2
let num2 = 20
let num3 = num1-- + num2 // 22
let num4 = num1 + num2 // 21
Первый сначала уменьшает num1 на 1, а затем выполняет накопление с num2, а второй сначала накапливает с num2, а затем уменьшает num на 1. , другой унарный оператор сначала попытается преобразовать переменную в число
логический оператор
Логические операторы И и логические НЕ являются операциями короткого замыкания, то есть первый операнд определяет результат, а второй операнд не оценивается.
let num = 0
true || num++
console.log(num) //0
Следующая часто используемая логика и результаты суждений
первый операнд | оператор | второй операнд | результат |
---|---|---|---|
null | && | Любые | первый операнд |
undefined | && | Любые | первый операнд |
NaN | && | Любые | первый операнд |
false | && | Любые | первый операнд |
"" | && | Любые | первый операнд |
0 | && | Любые | первый операнд |
объект | && | Любые | второй операнд |
true | && | Любые | второй операнд |
Когда первый аргумент ложен, логическое И возвращает первый операнд, в противном случае возвращает второй операнд.
Вот список всех ложных значений: false, null, undefined, 0, NaN, ""
Логика или с логикой и наоборот, следующие общие результаты логики или суждения
первый операнд | оператор | второй операнд | результат |
---|---|---|---|
null | || | Любые | второй операнд |
undefined | || | Любые | второй операнд |
NaN | || | Любые | второй операнд |
false | || | Любые | второй операнд |
"" | || | Любые | второй операнд |
0 | || | Любые | второй операнд |
объект | || | Любые | первый операнд |
true | || | Любые | первый операнд |
Когда первый параметр равен false, логическое или возвращает второй операнд, в противном случае возвращает первый операнд.
Аддитивный оператор
В ECMAScript аддитивный оператор имеет некоторые особенности поведения, которые делятся на случаи со строками в операндах и без них.
Все строки рассматриваются как сращивание строк.Если одна из них является строкой, а другая не является строкой, она будет преобразована в строку, а затем сплайсирована, и тогда возникнут две ситуации.
- Второй операнд - это объект, он вызовет[[toPrimitive]]Преобразуйте его в исходное значение, если исходное значение является строкой, оно все равно будет выполнять конкатенацию строк.
- Если операнд не является объектом, он напрямую рассматривается как конкатенация строк.
console.log("123" + 123) // "123123"
console.log('123' + NaN) // "123NaN"
console.log("123" + {}) // "123[object Object]"
console.log("123" + undefined) // "123undefined"
Если оба операнда не являются строками, возможны два случая.
- операнд является объектом, он вызовет[[toPrimitive]]Преобразуйте его в исходное значение, если исходное значение является строкой, оно все равно будет выполнять конкатенацию строк.
- Если операнд не является объектом, он будет преобразован в числовой тип, а затем рассчитан
Стоит отметить, что конечными результатами четырех операций с участием NaN являются все NaN (другой операнд является строкой и по-прежнему рассматривается как конкатенация строк).
console.log(123 + true) // 124
console.log(123 + undefined) // NaN 因为 undefined 被转为 NaN
console.log(NaN + {}) // "NaN[object Object]" 含有对象会转为原始值,因为是字符串所以视为拼接
оператор отношения
Как и аддитивные операторы, реляционные операторы в JS (>, =,
- Если оба операнда числовые, выполнить числовое сравнение (если один из них NaN, всегда возвращать false)
- Два операнда представляют собой строки, сравнивающие кодовое значение строки одно за другим.
- где один из операндов является объектом, вызов[[toPrimitive]]Преобразование в исходное значение и сравнение в соответствии с предыдущими правилами
- Один из операндов — логическое значение, которое преобразуется в числовой тип, а затем выполняется сравнение
Для второй статьи, например
console.log('abc' < 'abd') // true
Внутренне он оценивается следующим образом.Поскольку оба являются строками, сначала оцените первый бит строки и найдите, что все они равны «a», затем сравните второй и найдите, что он одинаков, затем сравните третий, потому что "c" " имеет меньшую кодировку, чем "d" (первое 99, а второе 100), поэтому строка abc "меньше" строки abd
оператор равенства
Равные операторы и добавки, оператор связи является того же учителя, и есть много странных функций, так что сегодня сегодня я болел, сначала посмотрите на некоторые примеры онлайн.
undefined==null //true
[]==[] //false
[]==![] //true
{}==!{} //false
![]=={} //false
[]==!{} //true
[1,2]==![1] //false
Я не хочу подробно рассказывать об этом, друзья с хорошим английским могут проверить это напрямую.Технические характеристики, позвольте мне поговорить о личных навыках памяти
- Если типы совпадают, непосредственно определите, равны ли они, и неявное преобразование будет происходить для разных типов.
- Когда объект задействован, он вызывает[[toPrimitive]]
- NaN и ничего не хочет ждать, в том числе и себя
- Обе части уравнения будут максимально преобразованы в тип Number.Если это уже тот же тип на пути к номеру, то он не будет преобразован дальше.
- null и undefined имеют некоторые особенности поведения, прежде всего, это свободное равенство (==), но не строгое равенство (===), за исключением того, что ни одно значение не потеряет/строгое равенство с null/undefined
В общем, чтобы избежать ямы неявного преобразования, попробуйте использовать строгое равенство (===)
для заявления
Оператор for фактически является производным от оператора while. Оператор for содержит три выражения, разделенных точкой с запятой. Первое выражение обычно является объявлением или оператором присваивания, второе выражение является условием завершения цикла, а третье выражение является выражением для выполняться после одного цикла
let i = 0
for (;;i++){
//...
}
Приведенный выше код попадет в бесконечный цикл и вылетит из браузера, потому что второе выражение не задано, оно будет считаться всегда истинным, то есть цикл никогда не завершится, а переменная цикла i будет каждый раз +1, и нет начального оператора, сам код не имеет смысла, он просто означает, что три выражения цикла for необязательны
Если порядок выполнения оператора for отсортирован в соответствии с порядком выполнения, он выглядит так:
for (/* 1 */let i = 0;/* 2 */i < 10;/* 3 */i++) {
/* 4 */ console.log(i)
}
Последовательность 1 -> 2 -> 4 -> 3 -> 4 -> 3 -> 4 -> ... -> выход
в заявлении
Оператор for in возвращает свойства объекта,Возвращаемый порядок может варьироваться в зависимости от браузера, потому что спецификации нет, поэтому не полагайтесь на порядок, который он возвращает, в то время как Reflect.ownKeys , Object.getOwnPropertyNames , Object.getOwnPropertySymbols определяются алгоритмом [[OwnPropertyKeys]] спецификации ES6, который читается следующим образом
- Свойства, возвращающие целые числа первыми по порядку (свойства массивов)
- Возвращает строковые свойства по очереди в том порядке, в котором они были созданы
- Наконец возвращает все свойства символа
заявление этикетки
Используйте оператор label для добавления меток к оператору for.Когда оператор for выходит через операторы break и continue, вы можете дополнительно указать имя метки для выхода во внешний цикл, который будет использоваться в многоуровневых циклах for.
let num = 0
outer: for (let i = 0; i < 10; i++) {
for (let j = 0; j < 10; j++) {
if (i === 5 && j === 5) {
continue outer
}
num++
}
}
console.log(num) // 95
Когда i и j оба равны 5, 5 обходов (55, 56, 57, 58, 59) будут пропущены, а окончательный результат равен 95, то есть цикл выполняется 95 раз.
оператор переключения
В операторе switch, если каждое условие не записывает ключевое слово break для выхода из решения, произойдет проникновение условия.
let i = 25
switch (i) {
case 25:
console.log('25')
case 35:
console.log('35')
break;
default:
console.log('default')
}
// "25"
// "35"
i удовлетворяет первому случаю, поэтому печатается строка 25, но поскольку разрыва нет, она будетИгнорироватьВторое условие суждения напрямую выполняет утверждение второго случая, и если второе условие не имеет перерыва, он будет продолжать проникать в по умолчанию
Условие суждения случая в операторе switch строго равно, строка 10 не равна числу 10
функция
До ES6 аргументы функций хранились в файле с именемarguments
Объект создается при выполнении функции, он похож на массив, имеет свойство длины, представляющее количество параметров.Количество параметров здесь — это количество параметров, переданных при выполнении функции, а не количество параметров, определенных функцией.
function func(a,b,c) {
console.log(arguments)
}
func(1,2) // Arguments(2) [1, 2, callee: ƒ, Symbol(Symbol.iterator): ƒ, length:2]
Даже если определены три параметра, arguments отражает только количество параметров во время работы функции.Кроме того, у arguments есть некоторые особенности.в нестрогом режимеОн установит связь с параметрами времени выполнения функции, при изменении параметров это отразится на аргументах, и наоборот
function func(a,b,c) {
console.log(arguments)
a = 123
console.log(arguments)
}
func(1,2)
// Arguments(2) [1, 2, callee: ƒ, Symbol(Symbol.iterator): ƒ, length:2]
// Arguments(2) [123, 2, callee: ƒ, Symbol(Symbol.iterator): ƒ, length:2]
function func(a,b,c) {
console.log(a)
arguments[0] = 123
console.log(a)
}
func(1,2)
// 1
// 123
а такжестрогий режимЭта связь не установлена, они полностью разделены, хотя ES6 все еще может использовать аргументы.был заброшен, рекомендуется оператор rest (...)
Параметры функции передаются по значению, а не по ссылке, то есть если параметр является объектом, то внутри функции модификация объекта через формальный параметр будет отражать все переменные указывающие на этот параметр
let obj = {}
function func(o) {
o.a = '123'
}
console.log(obj) // {}
func(obj)
console.log(obj) // {a:"123"}
Поскольку оно передается по значению, переменная obj и формальный параметр o указывают на один и тот же объект памяти кучи.Свойство a добавляется к объекту через формальный параметр o внутри func, что будет отражено в переменной obj в момент в то же время.
Продолжение следует
использованная литература
Продвинутое программирование на JavaScript, 3-е издание
«JavaScript, которого вы не знаете»