赞
踩
JavaScript 高级
作者: 写代码的小鱼儿
Email:282505458@qq.com
QQ:282505458
微信:15311464808
说明:本文档用于学习交流,可传播可分享,如有错误,请联系小鱼儿,感谢矫正与探讨
对象名 = {}
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 构造函数名 一般使用这种方式
javascript中的每个对象都有prototype属性,Javascript中对象的prototype属性的解释是:返回对象类型原型的引用每一个构造函数都有一个属性叫做原型。这个属性非常有用:为一个特定类声明通用的变量或者函数。
你不需要显式地声明一个prototype属性,因为在每一个构造函数中都有它的存在。prototype 既是属性也是对象。
每个函数都有一个 prototype 属性,被称为原型对象,原型对象中的属性和方法可以通过实例对象访问。每个实例对象都有一个 __ proto__ 属性,指向该实例对象的构造函数。
可以根据这两个属性来判断该元素是函数还是对象。
//构造函数 构造函数名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)]
构造函数.prototype.属性 = 值;
构造函数.prototype.方法 = 值;通过原型对象添加属性可以简写为:
构造函数.prototype = {
手动加构造器
}
//构造函数 构造函数名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();
总结继承:
原型继承:改变原型的指向
借用构造函数继承:主要解决属性值不可改变的问题
原型继承 + 借用函数继承,既能解决属性的问题,又能解决方法继承的问题。
拷贝继承:就是把对象中需要共享的属性或方法,通过遍历的方式复制到另一个对象中。
函数的声明方式
(1)函数声明的方式
function 函数名 () {}
(2)函数表达式
function () {}
函数声明和函数表达式的区别:
函数声明如果放在 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指向 |
---|---|
普通函数 | 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的使用语法
函数名字.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(对象,参数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() 用于检索字符串中指定的子字符串,或检索与正则表达式相匹配的字符串,并返回起始位置。
参数:正则或要查询的字符。
返回值:查询字符的起始位置。
使用正则搜索字符串,不区分大小写:
var str = "hello world";
var n = search(/ld/i);
console.log(n);
使用字符搜索字符串,不区分大小写:
var str = "hello world";
var n = search("ld");
console.log(n);
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()检测字符串是不是匹配某个模式,如果有匹配文本则返回true,否则返回false。
redExp.test();
var res = /e/.test("the best thing in the life are free");
console.log(res);//true
检索字符串中正则的匹配。
redExp.exec();
/e/.exec("this is the best thing , free");
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。