创建对象的三种方式
对象字面量
对象名 = {}
var obj = {
name : '张三',
age : 20,
say : function () {
console.log('say...');
}
}
系统构造函数,工厂模式
对象名 = new Object();
function createObject (name,age) {
var obj = new Object();
obj.name = name;
obj.age = age;
obj.say = function () {
console.log('say....');
}
}
自定义构造函数
原理同工厂模式,方法名首字母大写。自定义构造函数自动做了四件事:
a: 在内存中创建新的对象
b: this 指向这个对象
c: 给这个对象添加属性和方法
d: 返回这个新对象
function Person (name,age) {
this.name = name;
this.age = age;
this.say = function () {
console.log('say...');
}
}
检测对象是否是某个构造函数实例化的结果
(1)对象.instanceof.构造方法
(2)对象.constructor == 构造方法
工厂模式创建对象与构造函数创建对象的区别
工厂模式:
函数名小驼峰命名法,函数内部有new,返回值为所创建对象。直接调用函数创建对象。实例对象的构造类都是Object,不方便区分是哪一类。
构造函数:
函数名大驼峰命名法,函数内部没有new,没有返回值,this代指当前对象,通过new的方式创建对象。方便区分是某类的对象,可以用instanceof检测
构造函数与实例对象的区别
function Person(name, age, sex){
this.name = name;
this.age = age;
this.sex = sex;
this.say = function(){
console.log("say....");
};
}
var p = new Person("aa", 13, "男");
//构造函数与实例对象之间的关系
//实例对象是通过构造函数创建出来的
//console.dir打印对象结构
console.dir(p);
//打印实例对象
console.dir(Person);
//打印构造函数
//constructor实例对象的构造器 指向的是Person 所以这个实例对象是通过Person来创建的
console.log(p.__proto__.constructor == Person.prototype.constructor); console.log(p.constructor == Person);
结论:
实例对象是通过构造函数创建的 可以通过 实例对象.构造器 == 构造函数名 来判断对象是不是这个构造函数创建的 对象 instanceof 构造函数名 一般使用这种方式
原型
原型的引入
//构造函数 构造函数名Person
function Person(name, age){
this.name = name;
this.age = age;
this.say = function(){
console.log("say");
};
}
//得到一个实例对象
var p1 = new Person("aa", 34);
var p2 = new Person("bb", 45);
//这两个方法是否是同一个方法? 不是同一个方法
p1.say();
p2.say();
结论:
通过上述方式创建的对象,分别拥有自己的属性和方法。如果多个实例对象拥有同样的方法,采用这种方式比较浪费空间,可以采用原型对象的方式,将共有的属性和方法存储在原型对象中,实现空间共享,节省空间。
原型的作用
数据共享
在构造函数中定义的属性和方法,在实例对象的时候,实例对象的属性和方法都是在自己的空间中存在的。如果实例化多个对象,那么这些属性和方法都会存储在单独的空间,为了节省内存空间,我们会把对象共有的属性或方法写在原型对象中,实现节省内存空间。
改变this指向
原型对象中的this指向为实例对象,指向可以改变。
构造函数、实例、原型之间的关系
Javascript 规定,每一个构造函数都有一个 prototype 属性,指向另一个对象。 这个对象的所有属性和方法,都会被构造函数的实例继承。 这也就意味着,我们可以把所有对象实例需要共享的属性和方法直接定义在 prototype 对象上。
这时所有实例的 type 属性和 sayName() 方法, 其实都是同一个内存地址,指向 prototype 对象,因此就提高了运行效率。
任何函数都具有一个 prototype 属性,该属性是一个对象。
通过构造函数得到的实例对象内部会包含一个指向构造函数的 prototype 对象的指针 proto 。
总结: 任何函数都具有一个 prototype 属性,该属性是一个对象 构造函数的 prototype 对象默认都有一个 constructor 属性,指向 prototype 对象所在函数 通过构造函数得到的实例对象内部会包含一个指向构造函数的 prototype 对象的指针 proto 所有实例都直接或间接继承了原型对象的成员
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GkotGMpW-1577673827666)(/home/yujing/.config/Typora/typora-user-images/image-20191119103004205.png)]
通过原型对象添加方法
//构造函数 构造函数名Person
function Person(name, age){
this.name = name;
this.age = age;
}
//使用原型添加方法
Person.prototype.say = function(){
console.log("say....");
};
//判断两个方法是否是同一个方法
console.log(p1.say == p2.say); //true
结论:
使用原型对象创建属性和方法,在实例化对象中看不到这个属性或方法。
原型对象
实例对象中有一个__proto__的属性,就是原型,也是一个对象,这个属性是给浏览器使用,不是标准属性,__proto__可以叫原型对象
构造函数中有一个prototype的属性,就是原型,也是一个对象,这个是标准属性,这个属性是程序使用的。prototype可以叫原型对象
实例对象中的__proto__属性与构造函数中的prototype属性相等
实例对象是通过构造函数创建出来的,构造函数中有prototype原型对象
实例对象__proto__指向了构造函数中的原型对象
通过原型添加属性和方法
Person.prototype.classid = "220";
Person.prototype.eat = function(){
console.log("吃盒饭.....");
};
Person.prototype.study = function(){
console.log("吃饭睡觉打豆豆,就是不学习,因为我不学就会");
};
以上代码可以简写:
需要注意的是,需要手动添加 constructor 构造器
//使用原型添加属性和方法
Person.prototype = {
//手动添加构造器
constructor: Person,
classid: "220",
eat: function(){
console.log("吃饭的方法");
}
};
总结:实例对象与原型对象的关系
构造函数可以实例化对象。
构造函数中有一个属性叫prototype,是构造函数的原型对象。
构造函数的原型对象(prototype)中有一个constructor构造器,这个构造器指向的就是自己所在的原型对象所在的构造函数。
实例对象的原型对象(proto)指向的是该构造函数的原型对象。
实例对象属性与原型属性重名问题
当访问实例对象的某个属性的时候,首先会在实例对象的构造函数中寻找,找到了就直接使用,找不到就会按照原型链向原型对象中寻找。如果找不到,属性会返回 undefined 方法会返回 not a function
通过实例对象可以改变原型对象中的属性值吗?
不可以。如果想改变原型对象中属性的值,可以直接通过 原型对象.属性 = 值 的方式改变。
原型对象使用建议
私有成员(一般就是非函数成员)放到构造函数中 共享成员(一般就是函数)放到原型对象中 如果重置了 prototype 记得修正 constructor 的指向
可以为系统内置对象添加原型方法,相当于再改源码
String.prototype.myReverse=function () {
for(var i=this.length-1;i>=0;i--){
console.log(this[i]);
}
};
var str="abcdefg";
str.myReverse();
构造函数与实例对象的关系
-
实例对象是由构造函数所创建的;
-
实例对象中的 proto 中的 constructor指向构造函数 构造函数中的 constructor存储构造函数本身
验证一个实例对象是否是由某个构造函数产生的
对象 instanceof 构造方法 判断 建议用这个 对象.constructor = 构造方法名 返回布尔值
原型中的方法是可以互相访问的
function Animal(name,age) {
this.name=name;
this.age=age;
}
//原型中添加方法
Animal.prototype.eat=function () {
console.log("动物吃东西");
this.play();
};
Animal.prototype.play=function () {
console.log("玩球");
this.sleep();
};
Animal.prototype.sleep=function () {
console.log("睡觉了");
}
注意:
实例化对象与原型属性重名时,先寻找对象本身的属性,对象本身没有时再采用原型的属性,都没有时属性返回undefined,方法返回not a function
function Person(age,sex) {
this.age=age;//年龄
this.sex=sex;
this.eat=function () {
console.log("构造函数中的吃");
};
}
Person.prototype.sex="女";
Person.prototype.eat=function () {
console.log("原型对象中的吃");
};
var per=new Person(20,"男");
console.log(per.sex); //男
per.eat();//构造函数中的吃
原型链
原型链:是一种关系,实例对象和原型对象之间的关系,他们的关系 是通过原型 __ proto__ 来联系的。 每个构造函数都有一个 prototype 属性,每个实例对象都有一个 __ proto__ 属性,而 __ proto__ 属性指向构造函数的 prototype 属性。按照__ proto__ 寻找原型链的构造函数,会发现实例对象的顶端是 Object ,再向上寻找__ proto__ 会返回null。
//构造函数
function Person(name,age) {
//属性
this.name=name;
this.age=age;
//在构造函数中的方法
this.eat=function () {
console.log("吃吃吃");
};
}
//添加共享的属性
Person.prototype.sex="男";
//添加共享的方法
Person.prototype.sayHi=function () {
console.log("您好啊,"); };
//实例化对象,并初始化
var per=new Person("小明",20);
per.sayHi();
//如果想要使用一些属性和方法,并且属性的值在每个对象中都是一样的,方法在每个对象中的操作也都是一 样,那么,为了共享数据,节省内存空间,是可以把属性和方法通过原型的方式进行赋值
console.dir(per);
//实例对象的结构
console.dir(Person);
//构造函数的结构
//实例对象的原型__proto__和构造函数的原型prototype指向是相同的
//实例对象中的__proto__原型指向的是构造函数中的原型prototype
console.log(per.__proto__==Person.prototype);
//实例对象中__proto__是原型,浏览器使用的 //构造函数中的prototype是原型,程序员使用的
原型的指向是可以改变的
实例对象的原型 __ proto __ 指向的是该对象所在的构造函数的原型对象。如果构造函数的原型对象 prototype 指向发生了改变,实例对象的原型 __ proto__ 指向也会发生改变。实例对象和原型对象之间是通过 __ proto__ 原先来联系的,这个关系就是原型链。
//人的构造函数
function Person(age) {
this.age=10;
}
//人的原型对象方法
Person.prototype.eat=function () {
console.log("人的吃");
};
//学生的构造函数
function Student() {
}
Student.prototype.sayHi=function () {
console.log("嗨,小苏你好帅哦");
};
//学生的原型,指向了一个人的实例对象
Student.prototype=new Person(10); //改变了原型的指向
var stu=new Student();
stu.eat(); stu.sayHi();
原型的最终指向问题
Javascript 规定,每一个构造函数都有一个 prototype 属性,指向另一个对象。 这个对象的所有属性和方法,都会被构造函数的实例继承。 这也就意味着,我们可以把所有对象实例需要共享的属性和方法直接定义在 prototype 对象上。 prototype是对象,所以prototype这个对象中也有 proto ,指向了哪儿里?(对象中 proto 指 向的都是构造函数的prototype) 所以prototype这个对象中的 proto 指向的应该是某个构造函数的原型prototype
function Person() {
}
Person.prototype.eat=function () {
console.log("吃东西");
};
var per=new Person();
console.dir(per);
console.dir(Person);
//per实例对象的__proto__------->Person.prototype的__proto__---->Object.prototype的 __proto__是null
console.log(per.__proto__==Person.prototype); console.log(per.__proto__.__proto__==Person.prototype.__proto__); console.log(Person.prototype.__proto__==Object.prototype); console.log(Object.prototype.__proto__);
原型指向改变如何添加方法
如果原型的指向发生改变,那么应该在原型改变指向之后再添加原型方法。
//人的构造函数
function Person(age) {
this.age=age;
}
//人的原型中添加方法
Person.prototype.eat=function () {
console.log("正在吃东西");
};
//学生构造函数
function Student(sex) {
this.sex=sex;
}
//改变了原型对象的指向
Student.prototype=new Person(10);
//学生的原型中添加方法----先在原型中添加方法
Student.prototype.sayHi=function () {
console.log("哈喽哈喽");
};
var stu=new Student("男");
stu.eat();
stu.sayHi();
console.dir(stu);
继承
JS 不是一门面向对象的语言,它是一门基于对象的语言。我们学习 JS 的面向对象,是英文面向对象的思想适合人的想法,编程会更加方便,也利于后期的维护。
继承:首先继承是一种关系。
可以通过构造函数模拟类,然后通过改变原型指向来实现继承。继承也是为了实现数据共享。
缺陷:通过改变原型指向实现的继承,直接初始化了属性,继承过来的属性的值都是一样的。为了解决这一个问题,我们可以使用 call 函数。(指构造函数中的属性值不能改变)
继承的时候,可以不改变原型的指向,直接调用父级的构造函数的方式来为属性赋值就可以了。借用构造函数,把要继承的父级的构造函数拿过来,使用一下就可以了。
要借用的构造函数.call(要绑定函数的对象 [, 函数的参数1] [, 函数的参数2....] )
缺陷:父级中的方法不能继承。(指原型对象中的成员不能继承)
所以,为了完美实现继承,我们采用 原型继承 + 借用构造函数 来实现继承。
原型继承 + 借用构造函数 来实现继承
function Person(name,age,sex) {
this.name=name;
this.age=age;
this.sex=sex;
}
Person.prototype.sayHi=function () {
console.log("哈喽");
};
function Student(name,age,sex,score) {
//借用构造函数:属性值重复的问题
Person.call(this,name,age,sex);
this.score=score;
}
//改变原型指向----继承
Student.prototype=new Person();
//不传值 //改变原型指向后添加方法
Student.prototype.eat=function () {
console.log("吃东西");
};
var stu=new Student("小黑",20,"男","100分"); console.log(stu.name,stu.age,stu.sex,stu.score);
stu.sayHi();
stu.eat();
var stu2=new Student("小黑黑",200,"男人","1010分"); console.log(stu2.name,stu2.age,stu2.sex,stu2.score);
stu2.sayHi();
stu2.eat();
拷贝继承
把一个对象的竖向或方法通过遍历对象 直接复制到另一个对象中。
function Person() {}
Person.prototype.age=10;
Person.prototype.sex="男";
Person.prototype.height=100;
Person.prototype.play=function () {
console.log("玩的好开心");
};
var obj2={};
//Person的构造中有原型prototype,prototype就是一个对象,那么里面,age,sex,height,play都是 该对象中的属性或者方法
for(var key in Person.prototype){
obj2[key]=Person.prototype[key];
}
console.dir(obj2);
obj2.play();
总结继承:
原型继承:改变原型的指向
借用构造函数继承:主要解决属性值不可改变的问题
原型继承 + 借用函数继承,既能解决属性的问题,又能解决方法继承的问题。
拷贝继承:就是把对象中需要共享的属性或方法,通过遍历的方式复制到另一个对象中。
函数
函数声明和函数表达式的区别:
函数声明如果放在 if... else 分支结构中,在IE8 中会出现问题
//函数声明方式
if(true){
function f1() {
console.log("真区间函数");
}
}else{
function f1() {
console.log("假区间函数");
}
}
f1();//IE8 下返回 ‘假区间函数’
//函数表达式方式
var f2;
if(true){
f2=function () {
console.log("函数表达式--真区间");
};
}else{
f2=function () {
console.log("函数表达式--假区间");
};
}
f2();//所有浏览器都返回 "函数表达式--真区间"
函数中 this 指向
应用环境 | this指向 | 普通函数 | window | 对象方法 | 当前实例对象 | 定时器方法 | window | 构造函数 | 实例对象 | 原型对象方法 | 实例对象 |
---|
//普通函数中
this function f1() {
console.log(this);
} f1();
//定时器中的this
setInterval(function () {
console.log(this);
},1000);
//构造函数中this
function Person() {
console.log(this);
//对象方法中this
this.sayHi=function () {
console.log(this);
};
}
//原型中的方法中this
Person.prototype.eat=function () {
console.log(this);
};
var per=new Person();
console.log(per);
per.sayHi();
per.eat();
//严格模式 "use strict";
function f1() {
console.log(this);
//window
}
f1();
函数的不同调用方式
//普通函数
function f1() {
console.log("普通函数");
}
f1();
//构造函数---通过new 来调用,创建对象
function F1() {
console.log("我是构造函数");
}
var f=new F1();
//对象的方法
function Person() {
this.play=function () {
console.log("玩玩玩");
};
}
var per=new Person();
per.play();
函数是对象,对象不一定是函数
对象中有 proto 原型,函数中有prototype原型,如果一个结构里既有prototype,又有 proto , 说明是函数,也是对象
//对象中有__proto__原型,是对象 //函数中有prototype原型,是对象
function F1() { }
//函数中有prototype,也有__proto__
console.dir(F1);
//Math是对象 但不是函数没有prototype
console.dir(Math);
//所有的函数实际上都是Function的构造函数创建出来的实例对象
var f1=new Function("num1","num2","return num1+num2");
console.log(f1(1,2));
console.log(f1.__proto__==Function.prototype);
console.dir(f1);
console.dir(Function);
apply和call方法的使用
apply的使用语法
函数名字.apply(调用该函数的对象,[参数1,参数2,...]);
方法名字.apply(对象,[参数1,参数2,...]);
call的使用语法
函数名字.call(对象,参数1,参数2,...);
方法名字.call(对象,参数1,参数2,...);
作用:改变this的指向
不同的地方:参数传递的方式是不一样的,apply参数是数组 ,call是参数列,逗号分隔
只要是想使用别的对象的方法,并且希望这个方法是当前对象的,那么就可以使用apply或者是call的方法改变this的指向
注意:
apply和call方法中如果没有传入参数,或者是传入的是null,那么调用该方法的函数对象中的this就是 默认的window
//调用函数
function f1(x,y) {
console.log("结果是:"+(x+y)+this);
return "test";
}
f1(10,20);
//函数的调用
f1.apply();
f1.call();
f1.apply(null);
f1.call(null);
//apply和call方法中如果没有传入参数,或者是传入的是null,那么调用该方法的函数对象中的this就是 默认的window
f1.apply(null,[100,200]);
f1.call(null,100,200);
var result1=f1.apply(null,[10,20]);
var result2=f1.call(null,10,20);
console.log(result1);
console.log(result2);
bind() 复制
使用的语法:
函数名字.bind(对象,参数1,参数2,...);---->返回值是复制之后的这个函数 方法名字.bind(对象,参数1,参数2,...);---->返回值是复制之后的这个方法
复制了一份的时候,把参数传入到了f1函数中,x== >10,y==>20,null就是this,默认就是window bind方法是复制的意思,参数可以在复制的时候传进去,也可以在复制之后调用的时候传入进去 apply和call是调用的时候改变this指向 bind方法,是复制的时候,改变了this的指向
function f1(x, y) {
console.log((x + y) + ":=====>" + this.age);
}
function Person() {
this.age = 1000;
}
Person.prototype.eat = function () {
console.log("这个是吃");
};
var per = new Person();
var ff = f1.bind(per, 10, 20);
ff();
函数中的几个成员
name:函数的名字,name 属性是只读的,不能修改
arguments:实参 arguments[i] 实参的值 arguments.length 实参的个数
length:形参的个数
caller:函数的调用者
闭包
闭包的概念:函数A中,有一个函数B,函数B中可以访问函数A中定义的变量或者是数据,此时形成了闭包(这 句话暂时不严谨)
闭包的模式:函数模式的闭包,对象模式的闭包
闭包的作用:缓存数据,延长作用域链
**闭包的优点和缺点:**缓存数据
//函数模式的闭包:在一个函数中有一个函数
function f1() {
var num=10;
//函数的声明
function f2() {
console.log(num);
}
//函数调用
f2();
}
f1();//10
//对象模式的闭包:函数中有一个对象
function f3() {
var num=10;
var obj={
age:num
};
console.log(obj.age);//10
}
f3();
//普通的函数
function f1() {
var num = 10;
num++;
return num;
}
console.log(f1());
console.log(f1());
console.log(f1());
//函数模式的闭包
function f2() {
var num = 10;
return function () {
num++;
return num;
}
}
var ff = f2();
console.log(ff()); //11
console.log(ff()); //12
console.log(ff()); //13
总结:
如果想要缓存数据,就把这个数据放在外层的函数和里层的函数的中间位置 闭包的作用:缓存数据.优点也是缺陷,没有及时的释放 局部变量是在函数中,函数使用结束后,局部变量就会被自动的释放 闭包后,里面的局部变量的使用作用域链就会被延长
沙箱
环境,在一个虚拟的环境中模拟真实世界,做实验,实验结果和真实世界的结果是一样,但是不会影响真实世 界。
var num=10;
console.log(num+10);
//沙箱---小环境
(function () {
var num=10;
console.log(num);
})();
//沙箱---小环境
(function () {
var num=20;
console.log(num+10);
}());
var num=100;
(function () {
var num=10;
console.log(num);//10
}());
console.log(num);//100
递归
函数中调用函数自己,此时就是递归,递归一定要有结束的条件。
//递归实现:求n个数字的和 n=5---> 5+4+3+2+1
//函数的声明
function getSum(x) {
if(x==1){
return 1;
}
return x+getSum(x-1);
}
//函数的调用
console.log(getSum(5));
//递归案例:求斐波那契数列
function getFib(x) {
if(x==1||x==2){
return 1
}
return getFib(x-1)+getFib(x-2);
}
console.log(getFib(12));
浅拷贝
拷贝就是复制,就相当于把一个对象中的所有的内容,复制一份给另一个对象,直接复制,或者说,就是把一个 对象的地址给了另一个对象,他们指向相同,两个对象之间有共同的属性或者方法,都可以使用
var obj1={
age:10,
sex:"男",
car:["benchi","hafu","baoma","aodi"]
};
//另一个对象
var obj2={};
//写一个函数,作用:把一个对象的属性复制到另一个对象中,浅拷贝
//把a对象中的所有的属性复制到对象b中
function extend(a,b) {
for(var key in a){
b[key]=a[key];
}
}
extend(obj1,obj2);
console.dir(obj2);
console.dir(obj1);
深拷贝
拷贝还是复制,深:把一个对象中所有的属性或者方法,一个一个的找到.并且在另一个对象中开辟相应的空 间,一个一个的存储到另一个对象中。两者内存地址不同。
var obj1={
age:10,
sex:"男",
car:["benchi","hafu","baoma","aodi"],
dog:{
name:"大黄",
age:5,
color:"黑白色"
} };
var obj2={};//空对象
//通过函数实现,把对象a中的所有的数据深拷贝到对象b中
function extend(a,b) {
for(var key in a){ //先获取a对象中每个属性的值 var item=a[key]; //判断这个属性的值是不是数组
if(item instanceof Array){
//如果是数组,那么在b对象中添加一个新的属性,并且这个属性值也是数组
b[key]=[];
//调用这个方法,把a对象中这个数组的属性值一个一个的复制到b对象的这个数组属性中 extend(item,b[key]);
}else if(item instanceof Object){
//判断这个值是不是对象类型的
//如果是对象类型的,那么在b对象中添加一个属性,是一个空对象
b[key]={};
//再次调用这个函数,把a对象中的属性对象的值一个一个的复制到b对象的这个属性对象中 extend(item,b[key]);
}else{ //如果值是普通的数据,直接复制到b对象的这个属性中
b[key]=item;
}
}
}
extend(obj1,obj2);
console.dir(obj1);
console.dir(obj2);
浅拷贝与深拷贝的区别:
1.浅拷贝: 将原对象或原数组的引用直接赋给新对象,新数组,新对象/数组只是原对象的一个引用
2.深拷贝: 创建一个新的对象和数组,将原对象的各项属性的“值”(数组的所有元素)拷贝过来,是“值”而不是“引用”
正则表达式
元字符
. 表示的是:除了\n(换行)以外的任意的一个字符 "fdsfs238"
[] 表示的是:范围, [0-9] 表示的是0到9之间的任意的一个数字, "789" [0-9]
[1-7] 表示的是1到7之间的任意的一个数字
[a-z] 表示的是:所有的小写的字母中的任意的一个
[A-Z] 表示的是:所有的大写的字母中的任意的一个
[a-zA-Z] 表示的是:所有的字母的任意的一个
[0-9a-zA-Z] 表示的是: 所有的数字或者是字母中的一个
[] 另一个函数: 把正则表达式中元字符的意义干掉
[.] 就是一个.
| 或者
[0-9]|[a-z] 表示的是要么是一个数字,要么是一个小写的字母
() 分组 提升优先级 [0-9]|([a-z])|[A-Z]
([0-9])([1-5])([a-z]) 三组, 从左边开始计算
都是元字符,但是也可以叫限定符,下面的这些
* 表示的是:前面的表达式出现了0次到多次
[a-z][0-9]* 小写字母中的任意一个 后面是要么是没有数字的,要么是多个数字的 "fdsfs3223323"
+ 表示的是:前面的表达式出现了1次到多次 [a-z][9]+ 小写字母一个后面少一个9,或者多个9 "fesfewww9fefds"
? 表示的是:前面的表达式出现了0次到1次,少是0次,多1次 ,另一个含义:阻止贪婪模式 [4][a-z]? "1231234ij"
限定符:限定前面的表达式出现的次数
{} 更加的明确前面的表达式出现的次数
{0,} 表示的是前面的表达式出现了0次到多次,和 *一样的
{1,} 表示的是前面的表达式出现了1次到多次,和 +一样的
{0,1} 表示的是前面的表达式出现了0次到1次,和 ?一样的
{5,10} 表示的是前面的表达式出现了5次到10次 {4} 前面的表达式出现了4次
方括号用于查找某个范围内的字符:
^ 表示的是以什么开始,或者是取非(取反) ^[0-9] 以数字开头
^[a-z] 以小写字母开始
[^0-9] 取反,非数字
[^a-z] 非小写字母
[^0-9a-zA-Z_]
$ 表示的是以什么结束
[0-9][a-z]$ 必须以小写字母结束
^[0-9][a-z]$ 相当于是严格模式 "3f2432e" "4f"
修正符\元字符
\d 数字中的任意一个,
\D 非数字中的一个
\s 空白符中的一个
\S 非空白符
\w 非特殊符号
\W 特殊符号
\b 匹配单词边界
\uxxxx 查找以十六进制xxxx规定的Unicode字符
修饰符
g 全局匹配
i 不区分大小写
m 多行匹配
x 忽略正则表达式中的空白
U 拒绝贪婪
.* 贪婪模式
.*? 非贪婪模式
反向引用
当我们匹配一个字符串的时候,可能会需要获取原字符串中的内容,此时我们可以这样做
//源字符串
2017-10-14
//正则
(\d{4})-(\d{2})-(\d{2})
//需要转换成 10/14/2017的格式,就用到反向表达式
$2/$3/$1
在正则中被分组的字符,我们可以通过$1 $2 $3...来捕获,如果需要引用原字符串的内容,只需要引用对应的 $1 $2 $3...即可。
创建正则表达式对象
//1.通过构造函数创建对象
var reg=new RegExp(/\d{5}/);
//字符串
var str="我的电话是10086";
//调用方法验证字符串是否匹配
var flag=reg.test(str); console.log(flag);
//对象创建完毕--
var reg=new RegExp(/\d{5}/);
//调用方法验证字符串是否匹配
var flag=reg.test("我的电话是10086");
console.log(flag);
//2.字面量的方式创建正则表达式对象
var reg=/\d{1,5}/;
var flag=reg.test("小苏的幸运数字:888");
console.log(flag);
身份证号 /^\d{17}(\d|[a-z])$/
手机号 /^\d{11}$/
qq号 /^\d{5,11}$/
固话 /^\d{3,4}[-]\d{7,8}$/
邮箱 /^\w+@\w+( \ .\w+){1,3}$/
日期 /\d{4}-\d{1,2}-\d{1,2}/
表单验证思路:
利用失去焦点事件onblur,(同时定义一个布尔值作为返回值,用作最后整体提交),判断如果值为空则提示输入值,如果有值则判断格式是否正确,格式错误返回false,格式正确返回true,最后在提交表单时整体验证只有所有都为true才可以提交。
正则表达式中的方法
search()
search() 用于检索字符串中指定的子字符串,或检索与正则表达式相匹配的字符串,并返回起始位置。
参数:正则或要查询的字符。
返回值:查询字符的起始位置。
使用正则搜索字符串,不区分大小写:
var str = "hello world";
var n = search(/ld/i);
console.log(n);
使用字符搜索字符串,不区分大小写:
var str = "hello world";
var n = search("ld");
console.log(n);
repalce()
repalce()用指定字符替换其他字符,或替换与正则匹配的字符。
参数:要修改的字符/匹配的正则,要替换的字符。
返回值:修改后的字符串。
var ss = "this is a good day";
var nn = ss.replace("good","bad");
//var nn = ss.replace(/good/i,"bad");
console.log(nn);//this is a bad day
test()
test()检测字符串是不是匹配某个模式,如果有匹配文本则返回true,否则返回false。
redExp.test();
var res = /e/.test("the best thing in the life are free");
console.log(res);//true
exec()
检索字符串中正则的匹配。
redExp.exec();
/e/.exec("this is the best thing , free");
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!