Рубрики
Uncategorized

Дополнительные инструкции JS по объектно-ориентированному, Прототипированию, Наследованию, Закрытию, Регулярным выражениям Заставят Вас полюбить интерфейс (Дополнительно 2)

Автор оригинала: David Wong.

Расширенный JavaScript

Цели обучения:

  • Понимание Объектно-Ориентированного Мышления В Области Развития
  • Понимание шаблонов, связанных с Объектно-ориентированной разработкой JavaScript
  • Освоите использование регулярных выражений в JavaScript

Объектно-Ориентированное Введение

Базовое воплощение Объектно-ориентированного в программах

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

var std1 = { name: 'Michael', score: 98 }
var std2 = { name: 'Bob', score: 81 }

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

function printScore (student) {
  Console. log ('name: '+ student. name +'+' score: '+ student. score)
}

Если мы примем идею объектно-ориентированного программирования, то в первую очередь будем рассматривать не процесс выполнения программы.

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

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

Абстрактный Шаблон поведения данных (Класс):

function Student (name, score) {
  this.name = name
  this.score = score
}

Student.prototype.printScore = function () {
  Console. log ('name: '+ this. name + this. name' +'score: '+ this. score)
}

Создание конкретных объектов экземпляра (экземпляра) на основе шаблонов:

var std1 = new Student('Michael', 98)
var std2 = new Student('Bob', 81)

Объект экземпляра имеет свое собственное специфическое поведение (отправка сообщений объекту).:

Std1. printScore ()// => Name: Michael score: 98
Std2. printScore ()// => Name: Bob's score 81

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

Класс-это абстрактное понятие. Например, мы определяем Класс-Ученик, что относится к понятию ученики.

Пример-конкретный студент, например, Майкл и Боб-два конкретных студента.

Поэтому идея объектно-ориентированного проектирования заключается в:

  • Абстрактный Класс
  • Создать экземпляр из класса
  • Экземпляр команды для получения результатов

Объектно-ориентированная абстракция выше, чем функция, потому что класс содержит как данные, так и методы обработки данных.

Три способа создания объектов

1. Конструктор вызывающей системы

Мы можем создать его непосредственно через новый объект ():

var person = new Object()
person.name = 'Jack'
person.age = 18

person.sayName = function () {
  console.log(this.name)
}

2. Повышение грамотности

var person = {
  name: 'Jack',
  age: 18,
  sayName: function () {
    console.log(this.name)
  }
}

С вышеизложенным проблем нет, но что, если мы хотим создать два объекта экземпляра человека?

3. Создание Заводской Функции

Мы можем написать функцию для решения проблемы дублирования кода:

function createPerson (name, age) {
  return {
    name: name,
    age: age,
    sayName: function () {
      console.log(this.name)
    }
  }
}

Затем создается объект экземпляра:

var p1 = createPerson('Jack', 18)
var p2 = createPerson('Mike', 18)

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

Конструктор

Руководство по содержанию:

  • синтаксис конструктора
  • Аналитический конструктор
  • Отношения между конструкторами и объектами экземпляра

    • Атрибуты конструктора экземпляров
    • Оператор Instanceof
  • Разница между обычным вызовом функции и вызовом конструктора
  • Возвращаемое значение конструктора
  • Статические и экземплярные члены конструкторов

    • Функции также являются объектами
    • Элемент экземпляра
    • Статический элемент
  • Проблема конструктора

Более элегантные заводские функции: конструкторы

Более элегантная фабричная функция заключается в следующем: конструктор:

function Person (name, age) {
  this.name = name
  this.age = age
  this.sayName = function () {
    console.log(this.name)
  }
}

var p1 = new Person('Jack', 18)
p1.sayName() // => Jack

var p2 = new Person('Mike', 23)
p2.sayName() // => Mike

Выполнение кода конструктора синтаксического анализа

В приведенном выше примере функция Person () заменяет функцию createPerson (), но эффект реализации тот же.

Это почему?

Мы отмечаем, что код в Person () отличается от createPerson () следующими способами:

  • Создание объектов, которые не отображаются
  • Назначьте атрибуты и методы непосредственно этому объекту
  • Заявление об отсутствии возврата
  • Имена функций пишутся с заглавной буквы.

Чтобы создать экземпляр Person, необходимо использовать оператор new.

Вызов конструктора таким образом выполняется в четыре этапа:

  1. Создайте новый объект
  2. Назначьте область конструктора новому объекту (таким образом, это указывает на новый объект).
  3. Выполните код в конструкторе
  4. Возврат нового объекта

Ниже приведен конкретный псевдокод:

function Person (name, age) {
  // When you call Person () using the new operator, you actually create an object first.
  // var instance = {}
  // Then let the internal this point to the instance object
  // this = instance
  // All the next operations for this actually operate on instance

  this.name = name
  this.age = age
  this.sayName = function () {
    console.log(this.name)
  }

  // This is returned at the end of the function, which is instance.
  // return this
}

Отношения между конструкторами и объектами экземпляра

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

В _proto_ каждого объекта экземпляра также есть атрибут конструктора, который указывает на конструктор, создавший экземпляр:

console.log(p1.constructor === Person) // => true
console.log(p2.constructor === Person) // => true
console.log(p1.constructor === p2.constructor) // => true

Атрибут конструктора объекта изначально использовался для определения типа объекта. Однако более надежно использовать оператор instanceof, если вы хотите определить тип объекта:

console.log(p1 instanceof Person) // => true
console.log(p2 instanceof Person) // => true

Проблема конструктора

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

function Person (name, age) {
  this.name = name
  this.age = age
  this.type = 'human'
  this.sayHello = function () {
    console.log('hello ' + this.name)
  }
}

var p1 = new Person('lpz', 18)
var p2 = new Person('Jack', 16)

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

console.log(p1.sayHello === p2.sayHello) // => false

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

function sayHello = function () {
  console.log('hello ' + this.name)
}

function Person (name, age) {
  this.name = name
  this.age = age
  this.type = 'human'
  this.sayHello = sayHello
}

var p1 = new Person('lpz', 18)
var p2 = new Person('Jack', 16)

console.log(p1.sayHello === p2.sayHello) // => true

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

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

var fns = {
  sayHello: function () {
    console.log('hello ' + this.name)
  },
  sayAge: function () {
    console.log(this.age)
  }
}

function Person (name, age) {
  this.name = name
  this.age = age
  this.type = 'human'
  this.sayHello = fns.sayHello
  this.sayAge = fns.sayAge
}

var p1 = new Person('lpz', 18)
var p2 = new Person('Jack', 16)

console.log(p1.sayHello === p2.sayHello) // => true
console.log(p1.sayAge === p2.sayAge) // => true

До сих пор мы в основном решали проблему потери памяти конструкторами по-своему. Резюме

  • синтаксис конструктора
  • Аналитический конструктор
  • Отношения между конструкторами и объектами экземпляра

    • Атрибуты конструктора экземпляров
    • Оператор Instanceof
  • Проблема конструктора

прототип

Руководство по содержанию:

  • Использование прототипа объекта прототипа для решения проблемы конструктора
  • Анализ взаимосвязи между конструктором, прототипом объекта прототипа и объектом экземпляра
  • Принцип поиска элементов атрибута: Цепочка прототипов
  • Элементы в объекте экземпляра объекта прототипа для чтения и записи
  • Краткая форма объекта-прототипа
  • Прототип собственного объекта

    • Объект
    • Массив
    • Строка
  • Проблема объектов-прототипов
  • Предложения по использованию построенных функций и объектов-прототипов

Лучшее решение: прототип

Javascript указывает, что у каждого конструктора есть атрибут прототипа, указывающий на другой объект.

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

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

function Person (name, age) {
  this.name = name
  this.age = age
}

console.log(Person.prototype)

Person.prototype.type = 'human'

Person.prototype.sayName = function () {
  console.log(this.name)
}

var p1 = new Person(...)
var p2 = new Person(...)

console.log(p1.sayName === p2.sayName) // => true

На этом этапе атрибут type всех экземпляров и метод sayName () ,

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

Любая функция имеет атрибут прототипа, который является объектом.

function F () {}
console.log(F.prototype) // => object

F.prototype.sayHi = function () {
  console.log('hi!')
}

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

console.log(F.constructor === F) // => true

Объект экземпляра, полученный конструктором, содержит указатель u proto_ на объект-прототип конструктора.

var instance = new F()
console.log(instance.__proto__ === F.prototype) // => true

прото Нестандартные атрибуты.

Объекты экземпляра имеют прямой доступ к элементам объекта-прототипа.

instance.sayHi() // => hi!

Вывод:

  • Любая функция имеет атрибут прототипа, который является объектом
  • Объект-прототип конструктора по умолчанию имеет атрибут конструктора, указывающий на функцию, в которой находится объект-прототип.
  • Объект экземпляра, полученный конструктором, содержит указатель на объект-прототип конструктора. прототип
  • Все экземпляры прямо или косвенно наследуют элементы объектов-прототипов

Принцип поиска элементов атрибута: Цепочка прототипов

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

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

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

То есть, когда мы вызываем персону 1. sayName (), мы последовательно выполняем два поиска:

  • Во-первых, анализатор спрашивает: “Есть ли у экземпляра person 1 атрибут say Name?” Ответ: Нет.
  • Затем он продолжает поиск и спрашивает: “Имеет ли прототип человека 1 свойство say Name?” Ответ: Да.
  • Затем он считывает функцию, хранящуюся в объекте-прототипе.
  • Когда мы вызываем персону 2. sayName (), мы повторим тот же процесс поиска и получим те же результаты.

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

Вывод:

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

Пример объекта Чтение-Запись Элементов Прототипа объекта

Более простая грамматика прототипа

Мы заметили, что Человек. прототип был введен один раз для каждого атрибута и метода, добавленных в предыдущем примере.

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

function Person (name, age) {
  this.name = name
  this.age = age
}

Person.prototype = {
  type: 'human',
  sayHello: function () {
    Console. log ('My name is'+ this. name +', I'm' + this. age + age')
  }
}

В этом примере были заданы Персоны. прототип для нового объекта.

Преимущество этого заключается в том, что добавление участников в Person. прототип прост, но существует также проблема, связанная с тем, что объекты-прототипы теряют элементы конструктора.

Поэтому, чтобы конструктор указывал в правильном направлении, мы рекомендуем, чтобы:

function Person (name, age) {
  this.name = name
  this.age = age
}

Person.prototype = {
  Constructor: Person, // => Manually point the constructor to the correct constructor
  type: 'human',
  sayHello: function () {
    Console. log ('My name is'+ this. name +', I'm' + this. age + age')
  }
}

Прототип собственного объекта

Все функции имеют объекты атрибутов прототипов.

  • Все функции имеют объекты атрибутов прототипов.
  • Все функции имеют объекты атрибутов прототипов.
  • Все функции имеют объекты атрибутов прототипов.
  • Все функции имеют объекты атрибутов прототипов.
  • Все функции имеют объекты атрибутов прототипов.
  • Все функции имеют объекты атрибутов прототипов.

Упражнение: Расширение методов прототипа для объектов массива и строки

наследовать

Что такое наследование?

  • Наследование в реальной жизни
  • Наследование в порядке

Наследование атрибутов конструкторов: Заимствование конструкторов

function Person (name, age) {
  this.type = 'human'
  this.name = name
  this.age = age
}

function Student (name, age) {
  //Borrowing constructors to inherit attribute members
  Person.call(this, name, age)
}

Var S1 = Student ('Zhang San', 18)
Console. log (s1. type, s1. name, s1. age) / => human Zhang San18

Наследование метода прототипа конструкторов: наследование копирования (для в)

function Person (name, age) {
  this.type = 'human'
  this.name = name
  this.age = age
}

Person.prototype.sayName = function () {
  console.log('hello ' + this.name)
}

function Student (name, age) {
  Person.call(this, name, age)
}

//Prototype object copy inherits prototype object members
for(var key in Person.prototype) {
  Student.prototype[key] = Person.prototype[key]
}

Var S1 = Student ('Zhang San', 18)

S1. sayName ()// => Hello Zhangsan

Другой способ наследования: наследование прототипа

function Person (name, age) {
  this.type = 'human'
  this.name = name
  this.age = age
}

Person.prototype.sayName = function () {
  console.log('hello ' + this.name)
}

function Student (name, age) {
  Person.call(this, name, age)
}

// Implementing inheritance with prototype features
Student.prototype = new Person()

Var S1 = Student ('Zhang San', 18)

console.log(s1.type) // => human

S1. sayName ()// => Hello Zhangsan

Прогрессия функций

Различные сценарии, в которых это указывает на функцию

Способ вызова функции определяет различные направления этого:

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

  • Все функции являются примерами функций

вызов,применение,привязка

После понимания различных сценариев, на которые указывает эта функция, мы знаем, что в некоторых случаях мы ссылаемся на это для конкретной среды.

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

На практике, однако, наш JavaScript предоставляет нам некоторые функциональные методы, которые помогут нам более элегантно справиться с этой проблемой указания.

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

вызов

Метод call () вызывает функцию, которая имеет указанное значение и отдельно предоставленные параметры (список параметров).

Примечание: Этот метод работает так же, как метод apply (), за исключением того, что метод call () принимает список из нескольких параметров, в то время как метод apply () принимает массив из нескольких параметров.

Синтаксис:

fun.call(thisArg[, arg1[, arg2[, ...]]])

Параметры:

  • Этот шарг

    • Это значение, указанное во время выполнения функции Fun
    • Если указано значение null или undefined, внутреннее это указывает на окно
  • арг1, арг2, …

    • Список заданных параметров

применять

Метод apply () вызывает функцию с указанным значением и параметрами, представленными в виде массива (или объекта, аналогичного массиву).

Примечание: Этот метод аналогичен методу call (), за исключением того, что метод call () принимает список из нескольких параметров, в то время как метод apply () принимает массив из нескольких параметров.

Синтаксис:

fun.apply(thisArg, [argsArray])

Параметры:

  • Этот шарг
  • Массив аргументов

Функция Apply () очень похожа на функцию call (), но разница заключается в способе предоставления параметров.

Функция Apply () использует массив параметров вместо списка параметров. Например:

fun.apply(this, ['eat', 'bananas'])

связывать

Функция bind () создает новую функцию (называемую функцией привязки), которая имеет то же тело функции (атрибут вызова, встроенный в спецификацию ECMAScript 5), что и вызываемая функция (целевая функция функции привязки).

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

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

Синтаксис:

fun.bind(thisArg[, arg1[, arg2[, ...]]])

Параметры:

  • Этот шарг

    • Когда вызывается связанная функция, параметр указывается как этот при запуске исходной функции. Этот параметр недопустим, когда функция привязки вызывается с использованием оператора new.
  • арг1, арг2, …

    • Когда вызывается функция привязки, эти параметры передаются связанному методу перед аргументами.

Возвращаемое значение:

Возвращает копию исходной функции, измененной указанным значением this и параметрами инициализации.

Резюме

  • Позвонить-это то же самое, что подать заявку

    • Все они используются для вызова функций, и они вызываются немедленно.
    • Но вы можете указать направление этого внутри функции с помощью первого параметра при вызове функции.
    • При вызове вызова параметры должны передаваться в виде списка параметров, т. е. в порядке, разделенном запятыми.
    • Когда выполняется вызов apply, параметры должны быть массивом, а затем при выполнении элементы внутри массива извлекаются один за другим и передаются один за другим в соответствии с параметрами.
    • Если первый параметр указывает значение null или не определено, внутреннее это указывает на окно
  • связывать

    • Его можно использовать для указания направления внутреннего этого, а затем создать новую функцию, которая изменит направление этого.
    • Самая большая разница между вызовом и применением заключается в том, что привязка не вызывает
    • Ставка поддерживает передачу параметров. Он имеет особый способ передачи параметров. Существует два места для передачи параметров.

        1. Одновременно с привязкой он передается в виде списка параметров.
        1. При вызове он передается в виде списка параметров
      • Какие параметры передаются при привязке или при вызове?
      • Объедините два: параметры, переданные в привязке, и параметры, переданные в вызове, объединяются и передаются в функцию.

Другие члены функции

  • аргументы

    • Набор аргументов
  • вызывающий абонент

    • Вызывающий функцию
  • длина

    • Количество формальных параметров
  • имя

    • Название функции
function fn(x, y, z) {
  Console.log(fn.length)// => Number of formal parameters
  Console.log(arguments)//pseudo-array parameter set
  Console. log (arguments. callee === fn) // function itself
  Caller of console.log(fn.caller)//function
  The name of the console. log (fn. name) // => function
}

function f() {
  fn(10, 20, 30)
}

f()

Что такое закрытие

Закрытие-это функция, которая может считывать внутренние переменные других функций.

Потому что в Javascript только подфункции внутри функций могут считывать локальные переменные.

Поэтому замыкания можно просто понимать как “функции, определенные внутри функции”.

Таким образом, по сути, закрытие-это мост, соединяющий внутреннюю и внешнюю функции.

Использование затворов:

  • Внутренние элементы функции могут быть прочитаны вне функции
  • Пусть члены функции всегда живут в памяти

Некоторые примеры замыканий Пример 1:

var arr = [10, 20, 30]
for(var i = 0; i < arr.length; i++) {
  arr[i] = function () {
    console.log(i)
  }
}

Пример 2:

console.log(111)

for(var i = 0; i < 3; i++) {
  setTimeout(function () {
    console.log(i)
  }, 0)
}
console.log(222)

обычное выражение

  • Понимание базовой грамматики регулярных выражений
  • Обычные объекты, которые могут использовать JavaScript

Введение в регулярные выражения

Что такое регулярное выражение

Регулярное выражение-это логическая формула для строковой операции, которая заключается в формировании “обычной строки” с использованием предопределенных определенных символов и комбинаций этих конкретных символов. Эта “обычная строка” используется для выражения логики фильтрации строк.

Используйте регулярные выражения в JavaScript

Создание обычных объектов

Режим 1:

var reg = new Regex('\d', 'i');
var reg = new Regex('\d', 'gi');

Режим 2:

var reg = /\d/i;
var reg = /\d/gi;

дело

Регулярное извлечение

//1. Salary withdrawal
Var STR = Zhang San: 1000, Li Si: 5000, Wang Wu: 8000. ";
var array = str.match(/\d+/g);
console.log(array);
//2. Extract email address
var str = "[email protected],[email protected] [email protected] 2、[email protected] [email protected]";
var array = str.match(/\[email protected]\w+\.\w+(\.\w+)?/g);
console.log(array);
//3. Grouping extraction  
//3. The annual portion of the date of withdrawal  
2015-5-10var dateStr = '2016-1-5';
// The () in the regular expression is used as a grouping, and the results matched by the grouping are obtained with Regex. $1 $2 $3....
var reg = /(\d{4})-\d{1,2}-\d{1,2}/;
if (reg.test(dateStr)) {  console.log(RegExp.$1);}
//4. Extract each part of the mail
var reg = /(\w+)@(\w+)\.(\w+)(\.\w+)?/;
var str = "[email protected]";
if (reg.test(str)) {  console.log(RegExp.$1);  console.log(RegExp.$2);  
console.log(RegExp.$3);}

Регулярная замена

// 1. Replace all blanks
var str = "   123AD  asadf   asadfasf  adf ";
str = str.replace(/\s/g,"xx");
console.log(str);

// 2. Replace all, |,
var str = "abc,efg,123,abc,123,a";
str = str.replace(/,|,/g, ".");
console.log(str);

Случай: Проверка формы

QQ number: span>
Mailbox:
Mobile phone: span>
Birthday: span>
Name: span>
//Get the text box
var txtQQ = document.getElementById("txtQQ");
var txtEMail = document.getElementById("txtEMail");
var txtPhone = document.getElementById("txtPhone");
var txtBirthday = document.getElementById("txtBirthday");
var txtName = document.getElementById("txtName");

//
txtQQ.onblur = function () {
  // Get the span corresponding to the current text box
  var span = this.nextElementSibling;
  var reg = /^\d{5,12}$/;
  // Determine whether the validation is successful
  if(!reg.test(this.value) ){
    //Verification was unsuccessful
    Span. innerText = enter the correct QQ number;
    span.style.color = "red";
  }else{
    //Verification success
    span.innerText = "";
    span.style.color = "";
  }
};

//txtEMail
txtEMail.onblur = function () {
  // Get the span corresponding to the current text box
  var span = this.nextElementSibling;
  var reg = /^\[email protected]\w+\.\w+(\.\w+)?$/;
  // Determine whether the validation is successful
  if(!reg.test(this.value) ){
    //Verification was unsuccessful
    Span. innerText = Enter the correct EMail address.
    span.style.color = "red";
  }else{
    //Verification success
    span.innerText = "";
    span.style.color = "";
  }
};

Часть проверки формы инкапсулирована в виде функции:

var regBirthday = /^\d{4}-\d{1,2}-\d{1,2}$/;
Add Check (txtBirthday, regBirthday,'Please enter the correct date of birth');
// Add validation to text boxes
function addCheck(element, reg, tip) {
  element.onblur = function () {
    // Get the span corresponding to the current text box
    var span = this.nextElementSibling;
    // Determine whether the validation is successful
    if(!reg.test(this.value) ){
      //Verification was unsuccessful
      span.innerText = tip;
      span.style.color = "red";
    }else{
      //Verification success
      span.innerText = "";
      span.style.color = "";
    }
  };
}

Проверьте форму, добавив в элемент пользовательские атрибуты проверки:

QQ number:
Mailbox:
Mobile phone:
Birthday:
Name:
// All validation rules
var rules = [
  {
    name: 'qq',
    reg: /^\d{5,12}$/,
    Tip: "Please enter the correct QQ"
  },
  {
    name: 'email',
    reg: /^\[email protected]\w+\.\w+(\.\w+)?$/,
    Tip: "Please enter the correct email address"
  },
  {
    name: 'phone',
    reg: /^\d{11}$/,
    Tip: "Please enter the correct mobile phone number"
  },
  {
    name: 'date',
    reg: /^\d{4}-\d{1,2}-\d{1,2}$/,
    Tip: "Please enter the correct date of birth"
  },
  {
    name: 'cn',
    reg: /^[\u4e00-\u9fa5]{2,4}$/,
    Tip: "Please enter the correct name"
  }];

addCheck('frm');


// Add validation to text boxes
function addCheck(formId) {
  var i = 0,
      len = 0,
      frm =document.getElementById(formId);
  len = frm.children.length;
  for (; i < len; i++) {
    var element = frm.children[i];
    //Form Element Addition Validation with Name Attribute
    if (element.name) {
      element.onblur = function () {
        // Use dataset to get the value of data-custom attributes
        var ruleName = this.dataset.rule;
        var rule =getRuleByRuleName(rules, ruleName);

        var span = this.nextElementSibling;
        // Determine whether the validation is successful
        if(!rule.reg.test(this.value) ){
          //Verification was unsuccessful
          span.innerText = rule.tip;
          span.style.color = "red";
        }else{
          //Verification success
          span.innerText = "";
          span.style.color = "";
        }
      }
    }
  }
}

// Get rule objects by the name of the rule
function getRuleByRuleName(rules, ruleName) {
  var i = 0,
      len = rules.length;
  var rule = null;
  for (; i < len; i++) {
    if (rules[i].name == ruleName) {
      rule = rules[i];
      break;
    }
  }
  return rule;
}