国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

JS高級講解面向?qū)ο螅停^承,閉包,正則表達式,讓你徹底愛上前端(進階二)

source / 3532人閱讀

摘要:通過構造函數(shù)得到的實例對象內(nèi)部會包含一個指向構造函數(shù)的對象的指針。

JavaScript 高級

學習目標:

理解面向?qū)ο箝_發(fā)思想

掌握 JavaScript 面向?qū)ο箝_發(fā)相關模式

掌握在 JavaScript 中使用正則表達式


面向?qū)ο蠼榻B 程序中面向?qū)ο蟮幕倔w現(xiàn)

在 JavaScript 中,所有數(shù)據(jù)類型都可以視為對象,當然也可以自定義對象。
自定義的對象數(shù)據(jù)類型就是面向?qū)ο笾械念悾?Class )的概念。
我們以一個例子來說明面向過程和面向?qū)ο笤诔绦蛄鞒躺系牟煌帯?br>假設我們要處理學生的成績表,為了表示一個學生的成績,面向過程的程序可以用一個對象表示:

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

而處理學生成績可以通過函數(shù)實現(xiàn),比如打印學生的成績:

function printScore (student) {
  console.log("姓名:" + student.name + "  " + "成績:" + student.score)
}

如果采用面向?qū)ο蟮某绦蛟O計思想,我們首選思考的不是程序的執(zhí)行流程,

而是 Student 這種數(shù)據(jù)類型應該被視為一個對象,這個對象擁有 name 和 score 這兩個屬性(Property)。

如果要打印一個學生的成績,首先必須創(chuàng)建出這個學生對應的對象,然后,給對象發(fā)一個 printScore 消息,讓對象自己把自己的數(shù)據(jù)打印出來。

抽象數(shù)據(jù)行為模板(Class):

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

Student.prototype.printScore = function () {
  console.log("姓名:" + this.name + "  " + "成績:" + this.score)
}

根據(jù)模板創(chuàng)建具體實例對象(Instance):

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

實例對象具有自己的具體行為(給對象發(fā)消息):

std1.printScore() // => 姓名:Michael  成績:98
std2.printScore() // => 姓名:Bob  成績 81

面向?qū)ο蟮脑O計思想是從自然界中來的,因為在自然界中,類(Class)和實例(Instance)的概念是很自然的。

Class 是一種抽象概念,比如我們定義的 Class——Student ,是指學生這個概念,

而實例(Instance)則是一個個具體的 Student ,比如, Michael 和 Bob 是兩個具體的 Student 。

所以,面向?qū)ο蟮脑O計思想是:

抽象出 Class

根據(jù) Class 創(chuàng)建 Instance

指揮 Instance 得結果

面向?qū)ο蟮某橄蟪潭扔直群瘮?shù)要高,因為一個 Class 既包含數(shù)據(jù),又包含操作數(shù)據(jù)的方法。


創(chuàng)建對象三種方法 1、調(diào)用系統(tǒng)的構造函數(shù)

我們可以直接通過 new Object() 創(chuàng)建:

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

person.sayName = function () {
  console.log(this.name)
}
2、字面量創(chuàng)建
var person = {
  name: "Jack",
  age: 18,
  sayName: function () {
    console.log(this.name)
  }
}

對于上面的寫法固然沒有問題,但是假如我們要生成兩個 person 實例對象呢?

3、工廠函數(shù)創(chuàng)建

我們可以寫一個函數(shù),解決代碼重復問題:

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)

這樣封裝確實爽多了,通過工廠模式我們解決了創(chuàng)建多個相似對象代碼冗余的問題,
但卻沒有解決對象識別的問題(即怎樣知道一個對象的類型)。


構造函數(shù)

內(nèi)容引導:

構造函數(shù)語法

分析構造函數(shù)

構造函數(shù)和實例對象的關系

實例的 constructor 屬性

instanceof 操作符

普通函數(shù)調(diào)用和構造函數(shù)調(diào)用的區(qū)別

構造函數(shù)的返回值

構造函數(shù)的靜態(tài)成員和實例成員

函數(shù)也是對象

實例成員

靜態(tài)成員

構造函數(shù)的問題

更優(yōu)雅的工廠函數(shù):構造函數(shù)

一種更優(yōu)雅的工廠函數(shù)就是下面這樣,構造函數(shù):

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
解析構造函數(shù)代碼的執(zhí)行

在上面的示例中,Person() 函數(shù)取代了 createPerson() 函數(shù),但是實現(xiàn)效果是一樣的。

這是為什么呢?

我們注意到,Person() 中的代碼與 createPerson() 有以下幾點不同之處:

沒有顯示的創(chuàng)建對象

直接將屬性和方法賦給了 this 對象

沒有 return 語句

函數(shù)名使用的是大寫的 Person

而要創(chuàng)建 Person 實例,則必須使用 new 操作符。

以這種方式調(diào)用構造函數(shù)會經(jīng)歷以下 4 個步驟:

創(chuàng)建一個新對象

將構造函數(shù)的作用域賦給新對象(因此 this 就指向了這個新對象)

執(zhí)行構造函數(shù)中的代碼

返回新對象

下面是具體的偽代碼:

function Person (name, age) {
  // 當使用 new 操作符調(diào)用 Person() 的時候,實際上這里會先創(chuàng)建一個對象
  // var instance = {}
  // 然后讓內(nèi)部的 this 指向 instance 對象
  // this = instance
  // 接下來所有針對 this 的操作實際上操作的就是 instance

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

  // 在函數(shù)的結尾處會將 this 返回,也就是 instance
  // return this
}
構造函數(shù)和實例對象的關系

使用構造函數(shù)的好處不僅僅在于代碼的簡潔性,更重要的是我們可以識別對象的具體類型了。

在每一個實例對象中的_proto_中同時有一個 constructor 屬性,該屬性指向創(chuàng)建該實例的構造函數(shù):

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

對象的 constructor 屬性最初是用來標識對象類型的,
但是,如果要檢測對象的類型,還是使用 instanceof 操作符更可靠一些:

console.log(p1 instanceof Person) // => true
console.log(p2 instanceof Person) // => true
構造函數(shù)的問題

使用構造函數(shù)帶來的最大的好處就是創(chuàng)建對象更方便了,但是其本身也存在一個浪費內(nèi)存的問題:

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)

在該示例中,從表面上好像沒什么問題,但是實際上這樣做,有一個很大的弊端。那就是對于每一個實例對象,type 和 sayHello 都是一模一樣的內(nèi)容,每一次生成一個實例,都必須為重復的內(nèi)容,多占用一些內(nèi)存,如果實例對象很多,會造成極大的內(nèi)存浪費。

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

對于這種問題我們可以把需要共享的函數(shù)定義到構造函數(shù)外部:

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

這樣確實可以了,但是如果有多個需要共享的函數(shù)的話就會造成全局命名空間沖突的問題。

你肯定想到了可以把多個函數(shù)放到一個對象中用來避免全局命名空間沖突的問題:

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

至此,我們利用自己的方式基本上解決了構造函數(shù)的內(nèi)存浪費問題。
小結

構造函數(shù)語法

分析構造函數(shù)

構造函數(shù)和實例對象的關系

實例的 constructor 屬性

instanceof 操作符

構造函數(shù)的問題


原型

內(nèi)容引導:

使用 prototype 原型對象解決構造函數(shù)的問題

分析 構造函數(shù)、prototype 原型對象、實例對象 三者之間的關系

屬性成員搜索原則:原型鏈

實例對象讀寫原型對象中的成員

原型對象的簡寫形式

原生對象的原型

Object

Array

String

...

原型對象的問題

構造的函數(shù)和原型對象使用建議


更好的解決方案: prototype

Javascript 規(guī)定,每一個構造函數(shù)都有一個 prototype 屬性,指向另一個對象。

這個對象的所有屬性和方法,都會被構造函數(shù)的實例繼承。

這也就意味著,我們可以把所有對象實例需要共享的屬性和方法直接定義在 prototype 對象上。

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() 方法,

其實都是同一個內(nèi)存地址,指向 prototype 對象,因此就提高了運行效率。

任何函數(shù)都具有一個 prototype 屬性,該屬性是一個對象。

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

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

構造函數(shù)的 prototype 對象默認都有一個 constructor 屬性,指向 prototype 對象所在函數(shù)。

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

通過構造函數(shù)得到的實例對象內(nèi)部會包含一個指向構造函數(shù)的 prototype 對象的指針 __proto__。

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

proto 是非標準屬性。

實例對象可以直接訪問原型對象成員。

instance.sayHi() // => hi!

總結:

任何函數(shù)都具有一個 prototype 屬性,該屬性是一個對象

構造函數(shù)的 prototype 對象默認都有一個 constructor 屬性,指向 prototype 對象所在函數(shù)

通過構造函數(shù)得到的實例對象內(nèi)部會包含一個指向構造函數(shù)的 prototype 對象的指針 proto

所有實例都直接或間接繼承了原型對象的成員

屬性成員的搜索原則:原型鏈

了解了 構造函數(shù)-實例-原型對象 三者之間的關系后,接下來我們來解釋一下為什么實例對象可以訪問原型對象中的成員。

每當代碼讀取某個對象的某個屬性時,都會執(zhí)行一次搜索,目標是具有給定名字的屬性

搜索首先從對象實例本身開始

如果在實例中找到了具有給定名字的屬性,則返回該屬性的值

如果沒有找到,則繼續(xù)搜索指針指向的原型對象,在原型對象中查找具有給定名字的屬性

如果在原型對象中找到了這個屬性,則返回該屬性的值

也就是說,在我們調(diào)用 person1.sayName() 的時候,會先后執(zhí)行兩次搜索:

首先,解析器會問:“實例 person1 有 sayName 屬性嗎?”答:“沒有。

”然后,它繼續(xù)搜索,再問:“ person1 的原型有 sayName 屬性嗎?”答:“有。

”于是,它就讀取那個保存在原型對象中的函數(shù)。

當我們調(diào)用 person2.sayName() 時,將會重現(xiàn)相同的搜索過程,得到相同的結果。

而這正是多個對象實例共享原型所保存的屬性和方法的基本原理。

總結:

先在自己身上找,找到即返回

自己身上找不到,則沿著原型鏈向上查找,找到即返回

如果一直到原型鏈的末端還沒有找到,則返回 undefined


實例對象讀寫原型對象成員 更簡單的原型語法

我們注意到,前面例子中每添加一個屬性和方法就要敲一遍 Person.prototype 。

為減少不必要的輸入,更常見的做法是用一個包含所有屬性和方法的對象字面量來重寫整個原型對象:

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

Person.prototype = {
  type: "human",
  sayHello: function () {
    console.log("我叫" + this.name + ",我今年" + this.age + "歲了")
  }
}

在該示例中,我們將 Person.prototype 重置到了一個新的對象。

這樣做的好處就是為 Person.prototype 添加成員簡單了,但是也會帶來一個問題,那就是原型對象丟失了 constructor 成員。

所以,我們?yōu)榱吮3?constructor 的指向正確,建議的寫法是:

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

Person.prototype = {
  constructor: Person, // => 手動將 constructor 指向正確的構造函數(shù)
  type: "human",
  sayHello: function () {
    console.log("我叫" + this.name + ",我今年" + this.age + "歲了")
  }
}
原生對象的原型

所有函數(shù)都有 prototype 屬性對象。

Object.prototype

Function.prototype

Array.prototype

String.prototype

Number.prototype

Date.prototype

...

練習:為數(shù)組對象和字符串對象擴展原型方法


繼承 什么是繼承

現(xiàn)實生活中的繼承

程序中的繼承

構造函數(shù)的屬性繼承:借用構造函數(shù)
function Person (name, age) {
  this.type = "human"
  this.name = name
  this.age = age
}

function Student (name, age) {
  // 借用構造函數(shù)繼承屬性成員
  Person.call(this, name, age)
}

var s1 = Student("張三", 18)
console.log(s1.type, s1.name, s1.age) // => human 張三 18
構造函數(shù)的原型方法繼承:拷貝繼承(for-in)
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)
}

// 原型對象拷貝繼承原型對象成員
for(var key in Person.prototype) {
  Student.prototype[key] = Person.prototype[key]
}

var s1 = Student("張三", 18)

s1.sayName() // => hello 張三
另一種繼承方式:原型繼承
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)
}

// 利用原型的特性實現(xiàn)繼承
Student.prototype = new Person()

var s1 = Student("張三", 18)

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

s1.sayName() // => hello 張三
函數(shù)進階 函數(shù)內(nèi) this 指向的不同場景

函數(shù)的調(diào)用方式?jīng)Q定了 this 指向的不同:

這就是對函數(shù)內(nèi)部 this 指向的基本整理,寫代碼寫多了自然而然就熟悉了。
函數(shù)也是對象

所有函數(shù)都是 Function 的實例

call、apply、bind

那了解了函數(shù) this 指向的不同場景之后,我們知道有些情況下我們?yōu)榱耸褂媚撤N特定環(huán)境的 this 引用,

這時候時候我們就需要采用一些特殊手段來處理了,例如我們經(jīng)常在定時器外部備份 this 引用,然后在定時器函數(shù)內(nèi)部使用外部 this 的引用。

然而實際上對于這種做法我們的 JavaScript 為我們專門提供了一些函數(shù)方法用來幫我們更優(yōu)雅的處理函數(shù)內(nèi)部 this 指向問題。

這就是接下來我們要學習的 call、apply、bind 三個函數(shù)方法。

call

call() 方法調(diào)用一個函數(shù), 其具有一個指定的 this 值和分別地提供的參數(shù)(參數(shù)的列表)。

注意:該方法的作用和 apply() 方法類似,只有一個區(qū)別,就是 call() 方法接受的是若干個參數(shù)的列表,而 apply() 方法接受的是一個包含多個參數(shù)的數(shù)組。

語法:

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

參數(shù):

thisArg

在 fun 函數(shù)運行時指定的 this 值

如果指定了 null 或者 undefined 則內(nèi)部 this 指向 window

arg1, arg2, ...

指定的參數(shù)列表

apply

apply() 方法調(diào)用一個函數(shù), 其具有一個指定的 this 值,以及作為一個數(shù)組(或類似數(shù)組的對象)提供的參數(shù)。

注意:該方法的作用和 call() 方法類似,只有一個區(qū)別,就是 call() 方法接受的是若干個參數(shù)的列表,而 apply() 方法接受的是一個包含多個參數(shù)的數(shù)組。

語法:

fun.apply(thisArg, [argsArray])

參數(shù):

thisArg

argsArray

apply() 與 call() 非常相似,不同之處在于提供參數(shù)的方式。

apply() 使用參數(shù)數(shù)組而不是一組參數(shù)列表。例如:

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

bind

bind() 函數(shù)會創(chuàng)建一個新函數(shù)(稱為綁定函數(shù)),新函數(shù)與被調(diào)函數(shù)(綁定函數(shù)的目標函數(shù))具有相同的函數(shù)體(在 ECMAScript 5 規(guī)范中內(nèi)置的call屬性)。

當目標函數(shù)被調(diào)用時 this 值綁定到 bind() 的第一個參數(shù),該參數(shù)不能被重寫。綁定函數(shù)被調(diào)用時,bind() 也接受預設的參數(shù)提供給原函數(shù)。

一個綁定函數(shù)也能使用new操作符創(chuàng)建對象:這種行為就像把原函數(shù)當成構造器。提供的 this 值被忽略,同時調(diào)用時的參數(shù)被提供給模擬函數(shù)。

語法:

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

參數(shù):

thisArg

當綁定函數(shù)被調(diào)用時,該參數(shù)會作為原函數(shù)運行時的 this 指向。當使用new 操作符調(diào)用綁定函數(shù)時,該參數(shù)無效。

arg1, arg2, ...

當綁定函數(shù)被調(diào)用時,這些參數(shù)將置于實參之前傳遞給被綁定的方法。

返回值:

返回由指定的this值和初始化參數(shù)改造的原函數(shù)拷貝。

小結

call 和 apply 特性一樣

都是用來調(diào)用函數(shù),而且是立即調(diào)用

但是可以在調(diào)用函數(shù)的同時,通過第一個參數(shù)指定函數(shù)內(nèi)部 this 的指向

call 調(diào)用的時候,參數(shù)必須以參數(shù)列表的形式進行傳遞,也就是以逗號分隔的方式依次傳遞即可

apply 調(diào)用的時候,參數(shù)必須是一個數(shù)組,然后在執(zhí)行的時候,會將數(shù)組內(nèi)部的元素一個一個拿出來,與形參一一對應進行傳遞

如果第一個參數(shù)指定了 null 或者 undefined 則內(nèi)部 this 指向 window

bind

可以用來指定內(nèi)部 this 的指向,然后生成一個改變了 this 指向的新的函數(shù)

它和 call、apply 最大的區(qū)別是:bind 不會調(diào)用

bind 支持傳遞參數(shù),它的傳參方式比較特殊,一共有兩個位置可以傳遞

在 bind 的同時,以參數(shù)列表的形式進行傳遞

在調(diào)用的時候,以參數(shù)列表的形式進行傳遞

那到底以誰 bind 的時候傳遞的參數(shù)為準呢還是以調(diào)用的時候傳遞的參數(shù)為準

兩者合并:bind 的時候傳遞的參數(shù)和調(diào)用的時候傳遞的參數(shù)會合并到一起,傳遞到函數(shù)內(nèi)部

函數(shù)的其它成員

arguments

實參集合

caller

函數(shù)的調(diào)用者

length

形參的個數(shù)

name

函數(shù)的名稱

function fn(x, y, z) {
  console.log(fn.length) // => 形參的個數(shù)
  console.log(arguments) // 偽數(shù)組實參參數(shù)集合
  console.log(arguments.callee === fn) // 函數(shù)本身
  console.log(fn.caller) // 函數(shù)的調(diào)用者
  console.log(fn.name) // => 函數(shù)的名字
}

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

f()
什么是閉包

閉包就是能夠讀取其他函數(shù)內(nèi)部變量的函數(shù),

由于在 Javascript 語言中,只有函數(shù)內(nèi)部的子函數(shù)才能讀取局部變量,

因此可以把閉包簡單理解成 “定義在一個函數(shù)內(nèi)部的函數(shù)”。

所以,在本質(zhì)上,閉包就是將函數(shù)內(nèi)部和函數(shù)外部連接起來的一座橋梁。

閉包的用途:

可以在函數(shù)外部讀取函數(shù)內(nèi)部成員

讓函數(shù)內(nèi)成員始終存活在內(nèi)存中

一些關于閉包的例子
示例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的正則對象

正則表達式簡介

什么是正則表達式

正則表達式是對字符串操作的一種邏輯公式,就是用事先定義好的一些特定字符、及這些特定字符的組合,組成一個“規(guī)則字符串”,這個“規(guī)則字符串”用來表達對字符串的一種過濾邏輯。

JavaScript 中使用正則表達式 創(chuàng)建正則對象

方式1:

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

方式2:

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

案例 正則提取
 // 1. 提取工資
var str = "張三:1000,李四:5000,王五:8000。";
var array = str.match(/d+/g);
console.log(array);
// 2. 提取email地址
var str = "123123@xx.com,fangfang@valuedopinions.cn 286669312@qq.com 2、emailenglish@emailenglish.englishtown.com 286669312@qq.com...";
var array = str.match(/w+@w+.w+(.w+)?/g);
console.log(array);
// 3. 分組提取 ?
// 3. 提取日期中的年部分  
2015-5-10var dateStr = "2016-1-5";
// 正則表達式中的()作為分組來使用,獲取分組匹配到的結果用Regex.$1 $2 $3....來獲取
var reg = /(d{4})-d{1,2}-d{1,2}/;
if (reg.test(dateStr)) { ?console.log(RegExp.$1);}
// 4. 提取郵件中的每一部分
var reg = /(w+)@(w+).(w+)(.w+)?/;
var str = "123123@xx.com";
if (reg.test(str)) { ?console.log(RegExp.$1); ?console.log(RegExp.$2); ?
console.log(RegExp.$3);}
正則替換
// 1. 替換所有空白
var str = "   123AD  asadf   asadfasf  adf ";
str = str.replace(/s/g,"xx");
console.log(str);

// 2. 替換所有,|,
var str = "abc,efg,123,abc,123,a";
str = str.replace(/,|,/g, ".");
console.log(str);

案例:表單驗證
QQ號:
郵箱:
手機:
生日:
姓名:
//獲取文本框
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 () {
  //獲取當前文本框?qū)膕pan
  var span = this.nextElementSibling;
  var reg = /^d{5,12}$/;
  //判斷驗證是否成功
  if(!reg.test(this.value) ){
    //驗證不成功
    span.innerText = "請輸入正確的QQ號";
    span.style.color = "red";
  }else{
    //驗證成功
    span.innerText = "";
    span.style.color = "";
  }
};

//txtEMail
txtEMail.onblur = function () {
  //獲取當前文本框?qū)膕pan
  var span = this.nextElementSibling;
  var reg = /^w+@w+.w+(.w+)?$/;
  //判斷驗證是否成功
  if(!reg.test(this.value) ){
    //驗證不成功
    span.innerText = "請輸入正確的EMail地址";
    span.style.color = "red";
  }else{
    //驗證成功
    span.innerText = "";
    span.style.color = "";
  }
};

表單驗證部分,封裝成函數(shù):

var regBirthday = /^d{4}-d{1,2}-d{1,2}$/;
addCheck(txtBirthday, regBirthday, "請輸入正確的出生日期");
//給文本框添加驗證
function addCheck(element, reg, tip) {
  element.onblur = function () {
    //獲取當前文本框?qū)膕pan
    var span = this.nextElementSibling;
    //判斷驗證是否成功
    if(!reg.test(this.value) ){
      //驗證不成功
      span.innerText = tip;
      span.style.color = "red";
    }else{
      //驗證成功
      span.innerText = "";
      span.style.color = "";
    }
  };
}

通過給元素增加自定義驗證屬性對表單進行驗證:

QQ號:
郵箱:
手機:
生日:
姓名:
// 所有的驗證規(guī)則
var rules = [
  {
    name: "qq",
    reg: /^d{5,12}$/,
    tip: "請輸入正確的QQ"
  },
  {
    name: "email",
    reg: /^w+@w+.w+(.w+)?$/,
    tip: "請輸入正確的郵箱地址"
  },
  {
    name: "phone",
    reg: /^d{11}$/,
    tip: "請輸入正確的手機號碼"
  },
  {
    name: "date",
    reg: /^d{4}-d{1,2}-d{1,2}$/,
    tip: "請輸入正確的出生日期"
  },
  {
    name: "cn",
    reg: /^[u4e00-u9fa5]{2,4}$/,
    tip: "請輸入正確的姓名"
  }];

addCheck("frm");


//給文本框添加驗證
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];
    // 表單元素中有name屬性的元素添加驗證
    if (element.name) {
      element.onblur = function () {
        // 使用dataset獲取data-自定義屬性的值
        var ruleName = this.dataset.rule;
        var rule =getRuleByRuleName(rules, ruleName);

        var span = this.nextElementSibling;
        //判斷驗證是否成功
        if(!rule.reg.test(this.value) ){
          //驗證不成功
          span.innerText = rule.tip;
          span.style.color = "red";
        }else{
          //驗證成功
          span.innerText = "";
          span.style.color = "";
        }
      }
    }
  }
}

// 根據(jù)規(guī)則的名稱獲取規(guī)則對象
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;
}

文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/30046.html

相關文章

  • JS高級講解面向對象原型繼承閉包正則達式讓你徹底愛上前端進階

    摘要:通過構造函數(shù)得到的實例對象內(nèi)部會包含一個指向構造函數(shù)的對象的指針。 JavaScript 高級 學習目標: 理解面向?qū)ο箝_發(fā)思想 掌握 JavaScript 面向?qū)ο箝_發(fā)相關模式 掌握在 JavaScript 中使用正則表達式 面向?qū)ο蠼榻B 程序中面向?qū)ο蟮幕倔w現(xiàn) 在 JavaScript 中,所有數(shù)據(jù)類型都可以視為對象,當然也可以自定義對象。自定義的對象數(shù)據(jù)類型就是面向?qū)ο笾?..

    Nino 評論0 收藏0
  • JavaScript系列(四) - 收藏集 - 掘金

    摘要:函數(shù)式編程前端掘金引言面向?qū)ο缶幊桃恢币詠矶际侵械闹鲗Х妒健:瘮?shù)式編程是一種強調(diào)減少對程序外部狀態(tài)產(chǎn)生改變的方式。 JavaScript 函數(shù)式編程 - 前端 - 掘金引言 面向?qū)ο缶幊桃恢币詠矶际荍avaScript中的主導范式。JavaScript作為一門多范式編程語言,然而,近幾年,函數(shù)式編程越來越多得受到開發(fā)者的青睞。函數(shù)式編程是一種強調(diào)減少對程序外部狀態(tài)產(chǎn)生改變的方式。因此,...

    cfanr 評論0 收藏0
  • JS程序

    摘要:設計模式是以面向?qū)ο缶幊虨榛A的,的面向?qū)ο缶幊毯蛡鹘y(tǒng)的的面向?qū)ο缶幊逃行┎顒e,這讓我一開始接觸的時候感到十分痛苦,但是這只能靠自己慢慢積累慢慢思考。想繼續(xù)了解設計模式必須要先搞懂面向?qū)ο缶幊蹋駝t只會讓你自己更痛苦。 JavaScript 中的構造函數(shù) 學習總結。知識只有分享才有存在的意義。 是時候替換你的 for 循環(huán)大法了~ 《小分享》JavaScript中數(shù)組的那些迭代方法~ ...

    melody_lql 評論0 收藏0
  • JavaScript深入淺出

    摘要:理解的函數(shù)基礎要搞好深入淺出原型使用原型模型,雖然這經(jīng)常被當作缺點提及,但是只要善于運用,其實基于原型的繼承模型比傳統(tǒng)的類繼承還要強大。中文指南基本操作指南二繼續(xù)熟悉的幾對方法,包括,,。商業(yè)轉載請聯(lián)系作者獲得授權,非商業(yè)轉載請注明出處。 怎樣使用 this 因為本人屬于偽前端,因此文中只看懂了 8 成左右,希望能夠給大家?guī)韼椭?...(據(jù)說是阿里的前端妹子寫的) this 的值到底...

    blair 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<