持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第17天,点击查看活动详情
JavaScript对象
什么是对象
对象 == 实例。 1.现实世界的万物皆对象,对象是看得见摸得着的事物,比如一个水杯、一个人、一辆车。 2.对象是拥有属性和方法的数据。属性指与对象有关的值;方法指对象可以执行的行为或可以完成的功能。 比如一辆车的属性有品牌、型号、重量和颜色等,方法有启动、行驶、刹车减速、停止等。 所有汽车都有这些属性,但是每款车的属性都不尽相同。 所有汽车都拥有这些方法,但是它们被执行的时间都不尽相同。 3.JavaScript包含多种对象:①自定义对象、②内置对象、③文档对象、④浏览器对象。
1.自定义对象
1.创建对象的三种方式
1.利用字面量创建对象
使用大括号,括号里包含了对象的属性和方法。
var obj={};
var obj1 = {
/* 对象的属性 */
name: '张三',
age: 20,
sex: '男',
/* 对象的方法:定义了一个函数,并作为对象的属性存储 */
say: function() {
console.log('hello');
}
};
console.log(obj1); //打印对象的文本
console.log(obj1.toString()); //[object Object]
2.利用new Object创建对象
/* 2.利用new Object创建对象 */
var obj2 = new Object();
/* 对象的属性 */
obj2.name = "李四";
obj2.age = 20;
/* 对象的方法:定义了一个函数,并作为对象的属性存储 */
obj2.say = function() {
console.log('bye');
};
console.log(obj2); //打印对象的文本
console.log(obj2.toString()); //[object Object]
3.利用构造函数创建对象
构造函数是一种特殊的函数,只要是用来初始化对象,即为对象的成员变量赋初始值, 它总与new关键字一起使用,可以把对象中的一些公共的属性和方法抽取出来,然后封装到函数里。
/* 构造函数的语法格式 */
function 函数名() {
this.属性名 = 值; //此处分号去掉或者用逗号亦可
this.方法名 = function() {}; //此处分号去掉亦可
}
//利用构造函数创建对象
var obj3 = new 构造函数名();
/* 3.利用构造函数创建对象 */
function Person(name, age, sex) {
this.sex = sex; //此处分号去掉或者用逗号亦可
this.name = name;
this.age = age;
this.say = function() {
console.log('345');
}; //此处分号去掉亦可
}
var person = new Person('王五', 25, '男'); //创建对象
console.log(person); //打印对象的文本
console.log(person.toString()); //[object Object]
2.对象的使用
1.访问对象属性
1.方式1:对象名.属性名 2.方式2:对象名['属性名']
/* 1_1.访问对象属性 */
console.log("obj1.name:" + obj1.name); //1.访问对象的属性_对象名.属性名
console.log("obj1['name']:" + obj1['name']); //2.访问对象的属性_对象名['属性名']
2.调用对象方法
// 1_2.调用对象方法
obj1.say(); //3.调用对象的方法_对象名.方法名()
3.遍历对象的属性和方法
/* 1_3.遍历对象的属性和方法 */
for (var a in obj1) { //var可省略,key是属性,可以换成任意变量名
console.log(a); //属性名
console.log(obj1[a]); //属性值
console.log(obj.key); //undefined 此处这么写不能获取到属性值
}
4.for-in循环
1.for-in 语句用于循环对象属性, 循环中的代码每执行一次,就会对对象的属性进行一次操作。 2.ECMAScript对象的属性没有顺序。因此,通过for-in循环输出的属性名的顺序是不可预测的。 具体来说,所有属性都会被返回一次,但返回的先后次序可能会因浏览器而异。 3.for-in 也可以遍历数组,但不建议使用 for-in 语句来循环数组,因为会存在以下几个问题: 1.index索引为字符串型数字,不能直接进行几何运算; 2.遍历顺序有可能不是按照实际数组的内部顺序; 3.使用for in会遍历数组所有的可枚举属性,包括原型。
/* for-in循环遍历数组 */
var fruit = ["apple", "orange", "peach", "banana"];
for (var i in fruit) {
document.write(typeof i + "<br/>"); //string
document.write(i + ":" + fruit[i] + "<br/>");
}
练习: 创建一个对象,对象名称为forObj, 包含一个属性,属性名为readMe,属性值:'课堂小练习'; 一个方法,方法名为forArray,方法的具体执行逻辑为遍历数组(var a=["张三",''李四","王五"]), 最后再遍历这个对象。
2.常用内置对象
1.字符串对象 String
1.创建字符串对象
var str1 = "hello world";
var str2 = new String("hello word");
/* 严格地说,str1是一个基本类型中的string类型,不是引用类型中的String类型,也就不是一个对象。但它可以当作对象来用,即str1.之后可以加各种属性、方法。*/
console.log(typeof str1); //string
console.log(str1 instanceof Object); //false
console.log(str1 instanceof String); //false
console.log(typeof str2); //object
console.log(str2 instanceof Object); //true
console.log(str2 instanceof String); //true
以上两种创建字符串对象方式的深入研究:
/* str1与str2表示两个基本类型的变量 */
var str1 = "hello world";
var str2 = "hello world";
/* new是强制创建新对象,所以str3与str4不是引用同一个对象 */
var str3 = new String("hello word");
var str4 = new String("hello word");
/* 如下,变量名str1指向的内存空间与变量名str2指向的内存空间不同,它们是两个内存空间。 */
console.log(str1); //hello world
console.log(str2); //hello world
console.log(str1 == str2); //true,此处比较的是内存空间中放的那个值。
console.log(str1 === str2); //true
/* 如下,变量名str3指向的内存空间与变量名str4指向的内存空间不同,它们是两个内存空间。 */
console.log(str3); //{"0":"h","1":"e","2":"l","3":"l","4":"o","5":" ","6":"w","7":"o","8":"r","9":"d","length":10}
console.log(str4); //{"0":"h","1":"e","2":"l","3":"l","4":"o","5":" ","6":"w","7":"o","8":"r","9":"d","length":10}
console.log(str3 == str4); //false,此处比较的是内存空间的地址值,而不是内存空间中放的那个值。
console.log(str3 === str4); //false
/* 分析如下四行打印结果 */
var str5 = "hello world";
console.log(str5 == str2); //true,两个基本类型,值相等。
console.log(str5 === str2); //true,两个基本类型,值相等且类型相等。
console.log(str5 == str4); //false,基本类型的值与引用类型的地址,值不相等。
console.log(str5 === str4); //false,基本类型的值与引用类型的地址,值不相等且类型不相等。
2.获取字符串的长度
length 属性返回字符串的长度
var txt = "ABCDEF";
var sln = txt.length;
3.大小写转换方法
1.stringObj.toLowerCase() :把字符串转换为小写。 2.stringObj.toUpperCase() :把字符串转换为大写。
var str1="AbcdEfgh";
var str2=str1.toLowerCase();
alert(str2); //结果为"abcdefgh"
var str3=str1.toUpperCase();
alert(str3); //结果为"ABCDEFGH"
var text1 = "Hello World!";
var text2 = text1.toLowerCase();
var text3 = text1.toUpperCase();
4.提取某个字符
1.stringObj.charAt(index) :返回字符串中指定下标(位置)的字符。 2.stringObj.charCodeAt(index) :返回字符串中指定索引(位置)的字符 unicode 编码。 注:index是字符位置,从0开始。
var str1="JavaScript网页教程";
var str2=str1.charAt(12);
alert(str2); //结果为"教"
var str3=str1.charCodeAt(12);
alert(str3); //结果为25945
var str = "HELLO WORLD";
alert(str.charAt(0)); //返回"H"
var str = "HELLO WORLD";
alert(str.charCodeAt(0)); //返回72 0048-->4*16^1+8*16^0=72
5.查询指定字符串
1.stringObj.indexOf(findstr,index) :返回指定文本在字符串中首次出现的索引(位置)。 即返回findstr在stringObj中首次出现的索引(位置)。 findstr是查找的字符串。 index是开始查找的位置索引,index省略则代表从0开始找。 0 是字符串中的第一个位置,1 是第二个,2 是第三个...... 如果没有找到,则返回-1。 2.stringObj.lastIndexOf(findstr,index) :返回指定文本在字符串中最后一次出现的索引(位置)。 即返回findstr在stringObj中最后一次出现的索引(位置)。 findstr是查找的字符串。 index是结束查找的位置索引,index省略则代表到字符串末尾结束。 0 是字符串中的第一个位置,1 是第二个,2 是第三个...... 如果没有找到,则返回-1。
/* 1.stringObj.indexOf(findstr,index) */
var str = "The full name of China is the People's Republic of China.";
var pos = str.indexOf("China");
console.log(pos); //17
var str = "The full name of China is the People's Republic of China.";
var pos = str.indexOf("USA");
console.log(pos); //-1
var str = "The full name of China is the People's Republic of China.";
var pos = str.indexOf("China", 18);
console.log(pos); //51
/* 2.stringObj.lastIndexOf(findstr, index) */
var str = "The full name of China is the People's Republic of China.";
var pos = str.lastIndexOf("China");
console.log(pos); //51
var str = "The full name of China is the People's Republic of China.";
var pos = str.lastIndexOf("USA");
console.log(pos); //-1
var pos = str.lastIndexOf("China", 50);
console.log(pos); //17
var pos=str.lastIndexOf('China',53);
console.log(pos); //51 只要找到前面一个字符就认为找到了! 但是indexOf不会出现这个情况。
3.stringObj.search(findstr) :搜索特定值的字符串,并返回匹配的位置。
/* 3.stringObj.search(findstr) */
var str = "The full name of China is the People's Republic of China.";
var pos = str.search("China");
console.log(pos); //17
var str = "The full name of China is the People's Republic of China.";
var pos = str.search("USA");
console.log(pos); //-1
var str = "The full name of China is the People's Republic of China.";
var pos = str.search("China", 18);
console.log(pos); //17 第二个参数不起作用。
4.indexOf()和search() 的区别 1.search()的参数必须是正则表达式,而indexOf()的参数只是普通的字符串。 indexOf()是比search()更加底层的 方法。 2.如果只是对一个具体字符串来查找,那么使用indexOf()的系统资源消耗更小,效率更高; 如果查找具有某些特征的字符串(例如查找以a开头,后面是数字的字符串),那么indexOf()就无能为力,必 须要使用正则表达式和search()方法了。 3.大多时候用indexOf()不是真的想知道子字符串的位置,而是想知道长字符串中是否包含该子字符串。 如果返回索引为-1,那么说明没有,反之则有。
6.提取部分字符串
有三种提取部分字符串的方法:①slice(start, end); ②substring(start, end); ③substr(start, length);
1.slice() 方法:slice(start, end); 提取字符串的某个部分,并在新字符串中,返回被提取的部分。 该方法设置两个参数:起始索引(开始位置),终止索引(结束位置)。
var str = "Apple, Banana, Mango";
/* 1.截取字符串中位置 7 到位置 13 的片段 */
var res = str.slice(7, 13);
console.log(res); //Banana (含头不含尾)
/* 2.如果省略第二个参数,则该方法将截取字符串的剩余部分 */
var res2 = str.slice(7);
console.log(res2); //Banana, Mango
/* 3.如果某个参数为负,则从字符串的结尾开始计数。截取字符串中位置 -13 到位置 -7 的片段 */
var res3 = str.slice(-13, -7); //Banana
console.log(res3); //Banana ("含头不含尾")
/* 4.如果某个参数为负,则从字符串的结尾开始计数。截取字符串中位置 -13 到结尾的片段 */
var res4 = str.slice(-13);
console.log(res4); //Banana, Mango ("含头不含尾")
2.substring()方法:substring(start, end);
类似于 slice()方法,不同之处在于 substring() 无法接受负的索引,语法通过,但结果不正常。
不同之处在于 substring() 无法接受负的索引。
var str = "Apple, Banana, Mango";
/* 1.截取字符串中位置 7 到位置 13 的片段 */
var res = str.substring(7, 13);
console.log(res); //Banana (含头不含尾)
/* 2.如果省略第二个参数,则该方法将截取字符串的剩余部分 */
var res2 = str.substring(7);
console.log(res2); //Banana, Mango
/* 3.如果某个参数为负,则从字符串的结尾开始计数。截取字符串中位置 -13 到位置 -7 的片段 */
var res3 = str.substring(-13, -7); //Banana
console.log(res3); // (空)
/* 4.如果某个参数为负,则从字符串的结尾开始计数。截取字符串中位置 -13 到结尾的片段 */
var res4 = str.substring(-13);
console.log(res4); //Apple, Banana, Mango (全部打印出来)
3.substr()方法:substr(start, length);
类似于 slice()方法,不同之处在于第二个参数规定被提取部分的长度。第二个参数不能为负,因为它指的是长度。
/* 1.截取字符串中位置 7 开始往后总共 6 个字符片段 */
var str = "Apple, Banana, Mango";
var res = str.substr(7, 6);
console.log(res); //Banana (含头不含尾,长度为6的字符串)
/* 2.如果省略第二个参数,则该方法将截取字符串的剩余部分 */
var res2 = str.substr(7);
console.log(res2); //Banana, Mango
/* 3.如果某个参数为负,则从字符串的结尾开始计数。截取字符串中位置 -13 开始往后总共 6 个字符片段 */
var res3 = str.substr(-13, 6);
console.log(res3); //Banana ("含头不含尾")
/* 4.如果某个参数为负,则从字符串的结尾开始计数。截取字符串中位置 -13 到结尾的片段 */
var res4 = str.substr(-13);
console.log(res4); //Banana, Mango ("含头不含尾")
7.删除前后空白
stringObj.trim() :删除字符串两端的空白符。
var str = " Hello World! ";
alert(str.trim()); //"Hello World!"
8.连接字符串
stringObj.concat(str1,str2,...,strN) :连接两个或多个字符串。
var text1 = "Hello";
var text2 = "World";
var text3 = text1.concat(" ", text2); //将"Hello"、" "、"World"这三个字符串连接起来。
console.log(text3); //Hello World
/* concat()方法可用于代替加运算符,下面两行是等效的 */
var text4 = "Hello" + " " + "World!";
var text5 = "Hello".concat(" ", "World!");
console.log(text4); //Hello World!
console.log(text5); //Hello World!
9.拆分字符串
stringObj.split(bystr) :按照bystr字符串将stringObj字符串进行分割,返回分割后的字符串数组。
var str1 = "一,二,三,四,五,六,日";
var strArray = str1.split(",");
alert(strArray[1]); //结果为“二”
10.替换字符串
stringObj.replace(findstr,tostr) :用另一个值替换在字符串中指定的值。 findstr是要找的子字符串,tostr是替换为的字符串,返回替换后的新字符串,原字符串不变。 默认只替换首个匹配,如需替换所有匹配,需使用正则表达式的 g 标志(用于全局搜索)。 对大小写敏感,如需执行大小写不敏感的替换,需使用正则表达式 /i(大小写不敏感)。
var str = "Please visit Microsoft and Microsoft!";
/* 1.替换一个与多个 */
var str1 = str.replace("Microsoft", "W3School");
console.log(str1);
var str2 = str.replace(/Microsoft/g, "W3School");
console.log(str2);
/* 2.大小写敏感与否 */
var str3 = str.replace("MICROSOFT", "W3School");
console.log(str3);
var str4 = str.replace(/MICROSOFT/i, "W3School");
console.log(str4);
2.数值对象 Number
Number对象是原始数值的包装对象。
1.创建数值对象
var myNum1 = 123;
var myNum2 = new Number(123);
/* 严格地说,myNum1是一个基本类型中的number类型,不是引用类型中的Number类型,也就不是一个对象。但它可以当作对象来用,即myNum1.之后可以加各种属性、方法。*/
console.log(typeof myNum1); //number
console.log(myNum1 instanceof Object); //false
console.log(myNum1 instanceof Number); //false
console.log(typeof myNum2); //object
console.log(myNum2 instanceof Object); //true
console.log(myNum2 instanceof Number); //true
以上两种创建数值对象方式的深入研究:
/* num1与num1表示两个基本类型的变量 */
var num1 = 123;
var num2 = 123;
/* new是强制创建新对象,所以num3与num4不是引用同一个对象 */
var num3 = new Number(123);
var num4 = new Number(123);
/* 如下,变量名str1指向的内存空间与变量名str2指向的内存空间不同,它们是两个内存空间。 */
console.log(num1); //123
console.log(num2); //123
console.log(num1 == num2); //true,此处比较的是内存空间中放的那个值。
console.log(num1 === num2); //true
/* 如下,变量名num3指向的内存空间与变量名num4指向的内存空间不同,它们是两个内存空间。 */
console.log(num3); //{},F12开发者模式的控制台能看到123。
console.log(num4); //{},F12开发者模式的控制台能看到123。
console.log(num3 == num4); //false,此处比较的是内存空间的地址值,而不是内存空间中放的那个值。
console.log(num3 === num4); //false
/* 分析如下四行打印结果 */
var num5 = 123;
console.log(num5 == num2); //true,两个基本类型,值相等。
console.log(num5 === num2); //true,两个基本类型,值相等。
console.log(num5 == num4); //true,考虑此处如何解释?(除了此处,其他地方都与字符串情况一致)
console.log(num5 === num4); //false
2.数值转换为字符串
1.numberObj.toString() :数值转换为字符串。 2.numberObj.toFixed(count) :数值转换为字符串,并保留小数点后一定位数。 如果必要,该数字会被舍入,也可以用0补足。
var data = 23.56789;
alert(data.toFixed(2)); //23.57(四舍五入)
data = 23.5;
alert(data.toFixed(2)); //23.50
3.算术对象 Math
Math 对象用于执行数学任务。 没有构造函数Math()。无需创建,直接把Math作为对象使用,就可以调用其所有属性和方法。
1.常用属性
Math.PI:圆周率
console.log(Math.PI);//3.14159 圆周率
2.常用方法
1.Math.round(x) :返回的值是对x的小数点后面的数进行四舍五入。
Math.round(6.8); //返回 7
Math.round(2.3); //返回 2
2.Math.pow(x, y) :返回值是 x 的 y 次幂。
Math.pow(8, 2); //返回 64
3.Math.sqrt(x) : 返回 x 的平方根。
Math.sqrt(64); //返回 8
4.Math.abs(x) :返回 x 的绝对值:
Math.abs(-4.7); //返回 4.7
5.Math.ceil(x) :返回值是 x 上舍入最接近的整数:
Math.ceil(6.4);//返回 7
6.Math.floor(x) :返回值是 x 下舍入最接近的整数:
Math.floor(2.7);//返回 2
7.Math.min() :查找参数列表中的最低值。
Math.min(0, 450, 35, 10, -8, -300, -78); //返回 -300
8.Math.max() :查找参数列表中的最高值。
Math.max(0, 450, 35, 10, -8, -300, -78); //返回 450
9.Math.random() :返回介于 0(包括) 与 1(不包括) 之间的随机数。
Math.random(); //返回随机数 0.934984
10.Math.random()与Math.floor() 一起使用用于返回随机整数。
Math.floor(Math.random() * 10); //返回 0 至 9 之间的数
Math.floor(Math.random() * 11); //返回 0 至 10 之间的数
Math.floor(Math.random() * 10) + 1; //返回 1 至 10 之间的数
4.日期对象 Date
Date对象用于处理日期和时间。
1.创建日期对象
1.new Date() :用当前日期和时间创建新的日期对象(取得当前系统时间)。
var now = new Date(); //用当前日期和时间创建日期对象(取得当前系统时间)
console.log(now.toString()); //把 Date 对象转换为字符串。
console.log(now.toLocaleDateString()); //根据本地时间格式,把 Date 对象的日期部分转换为字符串。
console.log(now.toLocaleTimeString()); //根据本地时间格式,把 Date 对象的时间部分转换为字符串。
2.new Date(dateString) :用指定日期和时间创建新的日期对象。
var now = new Date("2021/8/20"); //"2021-8-20"、"2021 8 20"等等皆可。
console.log(now.toString()); //Fri Aug 20 2021 00:00:00 GMT+0800 (中国标准时间)
var now = new Date("2021/8/20 11:12");
console.log(now.toString()); //Fri Aug 20 2021 11:12:00 GMT+0800 (中国标准时间)
var now = new Date("October 13, 1975 11:13:00");
onsole.log(now.toString()); //Mon Oct 13 1975 11:13:00 GMT+0800 (中国标准时间)
3.new Date(milliseconds) :用指定毫秒值创建新的日期对象。 milliseconds为0时,对应1970年1月1日。
var now = new Date(0);
console.log(now.toString()); //Thu Jan 01 1970 08:00:00 GMT+0800 (中国标准时间)
var now = new Date(1137075575000);
console.log(now.toString()); //Thu Jan 12 2006 22:19:35 GMT+0800 (中国标准时间)
var now = new Date(-1137075575000);
console.log(now.toString()); //Wed Dec 20 1933 17:40:25 GMT+0800 (中国标准时间)
4.new Date(year, month, day, hours, minutes, seconds, milliseconds) :
用指定日期和时间创建新的日期对象。7个数字分别指定年、月、日、小时、分钟、秒和毫秒(按此顺序)。
var now = new Date(2018, 11, 24, 10, 33, 30, 10);
console.log(now.toString()); //Mon Dec 24 2018 10:33:30 GMT+0800 (中国标准时间)
JavaScript 从 0 到 11 计算月份。一月是 0,十二月是11,6个数字指定年、月、日、小时、分钟、秒。
var now = new Date(2018, 11, 24, 10, 33, 30);
console.log(now.toString()); //Mon Dec 24 2018 10:33:30 GMT+0800 (中国标准时间)
2个数字指定年份和月份。
var now = new Date(2018, 11);
console.log(now.toString()); //Sat Dec 01 2018 00:00:00 GMT+0800 (中国标准时间)
不能省略月份,如果只提供一个参数,则将其视为毫秒。
var now = new Date(2018);
console.log(now.toString()); //Thu Jan 01 1970 08:00:02 GMT+0800 (中国标准时间)
2.日期获取方法
获取方法用于获取日期的某个部分(来自日期对象的信息)。下面是最常用的方法:
| 方法 | 描述 |
|---|---|
| getTime() 或 valueOf() | 返回1970 年 1 月 1 日至今的毫秒数 |
| getFullYear() | 获取四位的年(yyyy) |
| getMonth() | 获取月(0-11) |
| getDate() | 以数值返回一个月中的某一天(1-31) |
| getDay() | 以数值返回一周中的某一天(0-6) |
| getHours() | 获取小时(0-23) |
| getMinutes() | 获取分(0-59) |
| getSeconds() | 获取秒(0-59) |
| getMilliseconds() | 获取毫秒(0-999) |
3.日期设置方法
设置方法用于设置日期的某个部分。下面是最常用的方法:
| 方法 | 描述 |
|---|---|
| setTime() | 以毫秒设置时间,返回设置的毫秒值 |
| setFullYear() | 设置年(可选月和日) |
| setMonth() | 设置月(0-11) |
| setDate() | 以数值设置月的某一天 (1 ~ 31) |
setDay() | 不存在这个方法 |
| setHours() | 设置小时(0-23) |
| setMinutes() | 设置分(0-59) |
| setSeconds() | 设置秒(0-59) |
| setMilliseconds() | 设置毫秒(0-999) |
4.案例
1.获取当前时间的时分秒,输出到浏览器。 2.实现小米抢购倒计时: 小米抢购开始时间为2021年9月1日0时0分0秒,计算当前时间距离抢购开始倒计时为多少天+时+分+秒。通过点 击一次按钮,获取实时的时间差。
5.正则表达式对象 RegExp
0.正则表达式
1.什么是正则表达式
正则表达式的概念:就是用一些特殊的字符来描述一个字符串的格式。 正则表达式的作用:验证一个字符串是否满足格式要求(即验证字符串格式是否匹配,不关心内容是否真实有效)。
2.正则表达式的语法
1.常用普通字符:用中括号括起来,用于查找某个范围内的字符。
| 正则表达式 | 含义 |
|---|---|
| [] | 表示任意一个字符 |
| [abc] | 表示a、b、c中任意一个字符(表示该字符是a或b或c) |
| [^abc] | 除了a、b、c的任意一个字符(表示该字符不能是a或b或c) |
| [a-z] | 表示从a到z中的任意一个字符(表示任意一个小写英文字母) |
| [h-z] | 表示从h到z中的任意一个字符(表示从h到z中的任意一个小写英文字母) |
| [A-Z] | 表示从A到Z中的任意一个字符(表示任意一个大写英文字母) |
| [1234] | 表示1、2、3、4中任意一个字符(表示该字符是1或2或3或4) |
| [^1234] | 除了1、2、3、4的任意一个字符(表示该字符不能是1或2或3或4) |
| [0-9] | 表示从0到9中的任意一个字符(表示任意一个数字) |
| [a-zA-Z0-9_] | 表示a到z、A到Z、0到9以及下滑线中的任意一个字符 |
[a-z&&[^bc]] | 表示a到z中除了b、c的任意一个字符,&&表示“与”的关系 |
2.常用转义字符:拥有特殊含义的字符。
| 正则表达式 | 含义 |
|---|---|
| . | 表示任意一个字符 |
| \d | 表示任意一个数字字符,相当于[0-9] |
| \D | 表示任意一个非数字字符,相当于 [^0-9] |
| \s | 表示任意一个空白字符,包括空格、制表符、换页符等等。 |
| \S | 表示任意一个非空白字符,相当于[^\s] |
| \w | 表示任意一个单词字符,相当于[a-zA-Z0-9_] |
| \W | 表示任意一个非单词字符,相当于[^\w] |
3.常用限定符:用于控制数量的字符。
| 正则表达式 | 含义 |
|---|---|
| ? | 表示前面的内容出现0到1次(\w?表示出现0-1个单词字符) |
| * | 表示前面的内容出现0到多次(\d*表示出现任意次数字) |
| + | 表示前面的内容出现1到多次(\s+表示至少出现一个空白) |
| {n} | 表示前面的字符重复n次(\d{11}表示出现11位数字) |
| {n,} | 表示前面的字符至少重复n次(\d{11,}表示出现11位或以上数字) |
| {n,m} | 表示前面的字符至少重复n次,并且小于等于m次,即X>=n && X<=m([a-zA-Z0-9]{6,15}表示数字和字母的组合出现6-15位) |
注:使用()将括号内的内容看做一个整体,如(1234){3,6}表示1234出现3-6次;(1234|5678){3,6}表示1234或5678出现3-6次。
4.常用定位符: 用来描述字符串或单词的边界。
| 正则表达式 | 含义 |
|---|---|
| ^ | 表示字符串必须以其后面约束的内容开始。当该符号在方括号表达式中使用时,表示不接受该方括号表达式中的字符集合。 |
| $ | 表示字符串必须以其前面约束的内容结尾 |
注:若正则表达式不书写^或$,正则表达式代表匹配部分内容,都加上则表示全匹配。
5.特殊字符: 一些有特殊含义的字符。若要匹配特殊字符,必须使字符"转义",即将反斜杠字符()放在其前面。
| 正则表达式 | 含义 | |
|---|---|---|
| [ | 反斜杠加左半边中括号,表示左半边中括号([) | |
| ] | 反斜杠加右半边中括号,表示右半边中括号(]) | |
| . | 反斜杠加一点,表示点(.) | |
| \ | 反斜杠加反斜杠,表示反斜杠() | |
| ? | 反斜杠加问号,表示问号(?) | |
| * | 反斜杠加星号,表示星号(*) | |
| + | 反斜杠加加号,表示加号(+) | |
| { | 反斜杠加左半边大括号,表示左半边大括号({) | |
| } | 反斜杠加右半边大括号,表示右半边大括号(}) | |
| ( | 反斜杠加左半边小括号,表示左半边小括号(() | |
| ) | 反斜杠加右半边小括号,表示右半边小括号()) | |
| | | 反斜杠加竖杠,表示竖杠( | ) |
| ^ | 反斜杠加上箭头,表示上箭头(^) | |
| $ | 反斜杠加美元符号,表示美元符号($) |
1.创建正则表达式对象
1.var rgExp= /pattern/modifiers; //简单方式 2.var rgExp=new RegExp("pattern","modifiers") ; //调用构造函数方式 说明: pattern是正则表达式, 描述了一个表达式模型; modifiers是修饰符(可选), 用于指定全局匹配、区分大小写的匹配和多行匹配 。
| 修饰符 | 描述 |
|---|---|
| i | 执行对大小写不敏感的匹配。 |
| g | 执行全局匹配(查找所有匹配而非在找到第一个匹配后停止)。 |
| m | 执行多行匹配 |
/* 1.字符串中不用加开始结束的/,但是表达式正文中的\必须使用\,进行转义才能生效。 */
//var reg1 = /^[0-9]{3,6}$/; //3-6位数字(省略修饰符)
var reg1 = /^\d{3,6}$/; //3-6位数字(省略修饰符)
console.log(reg1); //{"lastIndex":0}
console.log(reg1.toString()); //打印出:/^\d{3,6}$/
//var reg2=new RegExp("^[0-9]{3,6}$");//3-6位数字(省略修饰符)
var reg2 = new RegExp("^\d{3,6}$"); //3-6位数字(省略修饰符)
console.log(reg2); //{"lastIndex":0}
console.log(reg2.toString()); //打印出:/^\d{3,6}$/
/* 2.使用字符串创建的正则表达式时""也需要加转义符。即当使用构造函数创造正则对象时,需要常规的字符转义规则(在前面加反斜杠)。比如,以下是等价的: */
var reg1 = /\w+/; //一个或多个单词字符(省略修饰符)
console.log(reg1); //{"lastIndex":0}
console.log(reg1.toString()); //打印出:/\w+/
var reg2 = new RegExp("\w+"); //一个或多个单词字符(省略修饰符)
console.log(reg2); //{"lastIndex":0}
console.log(reg2.toString()); //打印出:/\w+/
2.RegExpObject.toString() 方法
返回正则表达式的字符串值。
3.RegExpObject.test(string) 方法
检测一个字符串是否匹配当前正则表达式,如果字符串中有匹配的值返回 true ,否则返回 false。 即如果字符串string中含有与RegExpObject匹配的文本则返回true,否则返回false。
/* 1.检测hello与world */
var reg = /hello/i; //hello字符串且忽略大小写
var a = reg.test("Hello World"); //检测
console.log(a); //true
var reg2 = new RegExp("world"); //world字符串
var a2 = reg2.test("Hello World"); //检测
console.log(a2); //false
/* 2.编写QQ号的验证:QQ全部由数字组成,QQ最少有五位 */
var reg2 = /^[1-9]\d{4,}$/;
console.log(reg2.test("18573")); //true
/* 3.验证手机号 */
var reg3 = /^1[3456789]\d{9}$/;
console.log(reg3.test("13856596677")); //true
/* 4.中括号的验证 */
var reg = /^[abcd]$/; //等价于var reg = new RegExp("^\[abcd\]$");
var a = reg.test("abcd");
var b = reg.test("[abcd]");
console.log(a); //false
console.log(b); //true
/* 5.点的验证 */
var reg = /^.1234.$/; //等价于var reg = new RegExp("^\.1234.$");
var a = reg.test("012345");
var b = reg.test(".1234@");
console.log(a); //false
console.log(b); //true
4.RegExpObject.exec(string) 方法
检索字符串中的正则表达式的匹配,如果字符串中有匹配的值返回该匹配值,否则返回 null。
var reg = /hello/i; //hello字符串且忽略大小写(将i换成gi,后面检测结果不变)
var a = reg.exec("Hello ada hello"); //检测
console.log(a);//{"0":"Hello","index":0,"input":"Hello ada hello","length":1}
document.write(a); //Hello
5.String对象中支持正则表达式的方法
1.stringObj.search(findstr) : 检索字符串中指定的子字符串,或检索与正则表达式相匹配的子字符串。 返回与指定查找的字符串或者正则表达式相匹配的首个 String 对象起始位置。 如果没有找到任何匹配的子串,则返回 -1。
/* 1.search方法可使用字符串作为参数,字符串参数会转换为正则表达式 */
var n2 = str.search("Runoob");
console.log(n2); //6
/* 2.使用正则表达式搜索"runoob"字符串,且不区分大小写 */
var str = "Visit Runoob!";
var n = str.search(/runoob/i); //即使写成str.search(/runoob/gi);也只会匹配首个而不会全部匹配。
console.log(n);//6
/* 3.获取与正则表达式reg相匹配的首个String对象起始位置 */
var reg = /i[t]+/i;
var str = "Visssitty Runoob Runoob "
var n = str.search(reg);
console.log(n); //5
2.stringObj.split(bystr ,limit) : 把一个字符串分割成字符串数组。该方法不改变原始字符串。 如果把空字符串 ("") 用作 separator,那么 stringObject 中的每个字符之间都会被分割。 bystr 可选字符串或正则表达式,从该参数指定的地方分割 stringObj。 limit可选,该参数可指定返回的数组的最大长度。 如果设置了该参数,返回的子串不会多于这个参数指定的数组。 如果没有设置该参数,整个字符串都会被分割,不考虑它的长度。
/* 1.用字符串分割,并指定返回的数组的最大长度为3 */
var str = "How are you doing today?";
var n = str.split(" ", 3);
console.log(n); //{"0":"How","1":"are","2":"you","length":3}
console.log(n.toString()); //How,are,you
/* 2.用正则表达式分割,并指定返回的数组的最大长度为3 */
var str = "How are you doing today?";
var n = str.split(/\s/, 3);
//var n = str.split(new RegExp("\s"), 3);
console.log(n); //{"0":"How","1":"are","2":"you","length":3}
console.log(n.toString()); //How,are,you
3.stringObj.replace(findstr,tostr) : 在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串。该方法不会改变原始字符串。 返回一个新的字符串,是用 tostr 替换了 findstr的第一次匹配或所有匹配之后得到的。
/* 使用正则表达式全局替换i开头的连续3个字母 */
var str = "visite Microsoft";
var n = str.replace(/i[a-z]{2}/g, "123");
console.log(str); //visite Microsoft
console.log(n); //v123te M123osoft
4.stringObj.match(regexp) : 在字符串内检索指定的值,或找到一个或多个正则表达式的匹配。 match() 方法将检索字符串 StringObj,以找到一个或多个与 regexp 匹配的文本。 这个方法的行为在很大程度上有赖于 regexp 是否具有标志 g。 如果 regexp 没有标志 g,那么 match() 方法就只能在 stringObject 中执行一次匹配。 如果没有找到任何匹配的文本, match() 将返回 null。 否则,它将返回一个数组,其中存放了与它找到的匹配文本有关的信息。
var str = "The rain in SPAIN stays mainly in the plain";
/* 1.全局查找字符串 "ain" */
var n = str.match(/ain/g);
console.log(n); //{"0":"ain","1":"ain","2":"ain","length":3}
console.log(n.toString()); //ain,ain,ain
/* 2.全局查找字符串 "ain",且不区分大小写 */
var n2 = str.match(/ain/gi);
console.log(n2); //{"0":"ain","1":"AIN","2":"ain","3":"ain","length":4}
console.log(n2.toString()); //ain,AIN,ain,ain
3.基本类型与引用类型
0.基本类型与引用类型的划分
1.基本类型:string类型、number类型、boolean类型、undefined、null。
2.引用类型统称为object类型,细分的话有:
1.Object类型;
2.自定义对象类型,如之前写的Person类型、Foo类型、Box类型等;
3.内置对象类型,如Array类型、Function类型、String类型、Number类型、Date类型、RegExp类型等。
1.引用类型的深入分析
1.引用类型:
1.引用类型是一种用于将数据和功能组织在一起的数据结构(也被称为类),引用类型的值(对象)是引用类型的一
个实例。
2.但是js中没有类的概念,因此引用类型也可以被称为对象定义,因为它们描述的是一类对象所具有的属性和方法。
3.对象是某个特定引用类型的实例,新对象是使用new操作符后跟一个构造函数来创建的,构造函数本身就是一个函
数,只不过该函数是出于创建新对象的目的而定义的。
4.ECMAScript提供了很多原生引用类型(如:Object、Array、Function等),以便开发人员用以实现常见的计算
任务。
5.js中的函数实际上是对象,每个函数都是Function类型的实例,而且都与其他引用类型一样具有属性和方法。
由于函数是对象,因此函数名实际上也是一个指向函数对象的指针,不会与某个函数绑定。如:
function sum(num1,num2){
return num1 + num2;
}
这与使用函数表达式定义函数的方法几乎相差无几:
var sum = function(num1,num2){
return num1 + num2;
}
2.基本包装类型:
1.为了便于操作基本数据类型值,js还提供了3个特殊的引用类型:Boolean、Number、String。这些类型与其他引
用类型相似,但有与各自的基本数据类型相应的特殊行为。
2.实际上,每当读取一个基本类型的时候,后台就会创建一个对应的基本包装类型的对象,从而让我们可以能够调用一
些方法来操作这些数据。如下:
var s1 = "hello,world";
var s2 = s1.substring(2);
尽管如我们所愿,基本类型调用了方法,但是基本类型不是对象,因而从逻辑上讲他们不应该具有方法。
3.其实,为了实现这种直观的操作,后台已经自动完成了一系列的处理。当第二行代码访问s1时,访问过程处于一种读
取模式,也就是从内存中读取这个字符串的值,而在读取模式中访问字符串时,后台都会自动完成以下处理:
a.创建String类型的一个实例;
b.在实例上调用指定的方法;
c.销毁这个实例。
经过处理,基本的字符串就变得跟对象一样了。
4.引用类型与基本包装类型的主要区别就是对象的生存期。使用new创建的引用类型实例,在执行流离开当前作用域之
前都一直保存在内存中,而自动创建的基本包装类型的对象,只存在一行代码的执行瞬间,然后立即被销毁。这也意
味着我们不能在运行时为基本类型值添加属性和方法。
3.单体内置对象:
1.单体内置对象是由ECMAScript实现提供的,不依赖宿主环境的对象,也就是开发人员不必显示地实例化内置对象,
因为它们已经实例化了。如:Global和Math。
2.实际上全局变量或全局函数是不存在的,所有在全局作用域中定义的
属性和函数,都是Global对象的属性。如:parseInt(),parseFloat()都是Global对象的方法。
2.基本类型与引用类型的比较
1.值的存放位置不同
1.基本类型的变量的值是存放在栈内存(Stack)里的。
1.存储在栈(stack)中的简单数据段,也就是说,它们的值直接存储在变量访问的位置。
2.因为这些原始类型占据的空间是固定的,所以可将他们存储在较小的内存区域–栈中。
3.这样存储便于迅速查寻变量的值。
2.引用类型的变量的值是保存在堆内存(Heap)中的对象(Object)。
1.存储在堆(heap)中的对象,也就是说,存储在变量处的值是一个指针(point),指向存储对象的内存地址。
2.这是因为引用值的大小会改变,所以不能把它放在栈中,否则会降低变量查寻的速度。
3.相反,放在变量的栈空间中的值是该对象存储在堆中的地址。
4.地址的大小是固定的,所以把它存储在栈中对变量性能无任何负面影响。
2.值本身是否可变不同
1.基本类型的值是不可变的,即基本类型的值是不可以添加属性和方法。
2.引用类型的值是可变的,即引用类型值可以动态的给添加属性和方法。
3.值的访问方式不同
1.基本数据类型的值是按值访问的。
2.引用类型的值是按引用访问的。
4.变量的比较含义不同
1.基本类型的变量的比较是它们的值的比较。
2.引用类型的变量的比较是引用的比较。
5.复制值的时候不同
1.基本类型复制值时,会重新创建一个新值,然后把值放到为新变量分配的空间上来(理解为栈中的空间)。
2.引用类型复制值时,会重新创建一个新值,然后把值放到为新变量分配的空间上来(理解为栈中的空间)。
但是不同的是新复制的值是一个指针,指向原值所在堆内存中的地址。
3.当使用=将一个变量赋值到另外的变量,实际上是将对应的值拷贝了一份,然后赋值给新的变量。我们把它称作值传递。
4.对象是通过引用传递,而不是值传递。也就是说,变量赋值只会将地址传递过去。
5.对于引用类型的变量,==和===只会判断引用的地址是否相同,而不会判断对象具体里属性以及值是否相同。因此,如果两个变量指向相同的对象,则返回true。
6.javascript引用数据类型是保存在堆内存中的对象,与其它语言不同的是,你不可以直接访问堆内存空间中的位置和操作堆内存空间。只能通过操作对象的在栈内存中的引用地址。所以引用类型的数据,在栈内存中保存的实际上是对象在堆内存中的引用地址。通过这个引用地址可以快速查找到保存在堆内存中的对象
7.一般而言,基本数据类型是有固定数目的字节组成,这些字节可以在解析器的较底层进行操作比如Number和Boolean;而引用数据类型,可以包含任意数目的属性和元素,因此它们无法像基本数据类型那样很容易的操作。由于,引用数据类型的值是会发生变化的,所以通过跟基本数据类型一样的值传递方式,也就没什么意义了,因为会牵涉到大量的内存的复制和比较,效率太低。所以引用数据类型是通过引用传递方式,实际传递的只是对象的一个地址。比如Array和Function因为它们都是特殊的对象所以它都是引用类型。另外,引用类型是可以添加属性,基本类型虽然也可以添加属性,也不会报错,经测试添加完之后却是无法访问的。如下:
var a = 12;
a.name = "myname";
console.log(a.name); // undefined
案例1:基本类型的复制。
var a = 10;
var b = a;
b = 20;
console.log(a); //10
var bl = true;
var bl1 = bl;
bl1 = false;
console.log(bl); //true
分析:b获取的值,是a值的一份拷贝,虽然两个变量的值是相等,但是两个变量保存两不同的基本数据类型值。b只是保存了a复制的一个副本。所以当b的值改变时,a的值依然是10。两个Boolean变量bl和bl1同样是基本数据类型,同样保存两个不同的基本数据据类型值,bl1保存bl复制的一个副本。下图演示了这种基本数据类型赋值的过程:
案例2:引用类型的复制。
var obj1 = new Object();
var obj2 = obj1;
obj2.name = "我有名字了";
console.log(obj1.name); //我有名字了
分析: 我们声明了一个引用数据类型变量obj1,并把它赋值给了另外一个引用数据类型变量obj2。当我们obj2添加了一个name属性并赋值"我有名字了"。obj1同样拥有了和obj2一样的name属性。说明这两个引用数据类型变量指向同一个堆内存对象。obj1赋值给obj2,实际只是把这个堆内存对象在栈内存的引用地址复制了一份给了obj2,但它们本质上共同指向了同一个堆内存对象。下面我们来演示这个引用数据类型赋值过程:
自然,给obj2添加name属性,实际上是给堆内存中的对象添加了name属性,obj2和obj1在栈内存中保存的只是堆内存对象的引用地址,虽然也是拷贝了一份,但指向的对象却是同一个。故而改变obj2引起了obj1的改变。
6.传递值的时候相同
没有差别。“ECMAScript中所有的函数都是按值传递的”。