JavaScript——对象

98 阅读35分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 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

image-20210314135445070.png

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

image-20210414222455311.png

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到zA到Z0到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类型、undefinednull2.引用类型统称为object类型,细分的话有:
  1.Object类型;
  2.自定义对象类型,如之前写的Person类型、Foo类型、Box类型等;
  3.内置对象类型,如Array类型、Function类型、String类型、Number类型、Date类型、RegExp类型等。

1.引用类型的深入分析

1.引用类型:
  1.引用类型是一种用于将数据和功能组织在一起的数据结构(也被称为类),引用类型的值(对象)是引用类型的一 
    个实例。
  2.但是js中没有类的概念,因此引用类型也可以被称为对象定义,因为它们描述的是一类对象所具有的属性和方法。
  3.对象是某个特定引用类型的实例,新对象是使用new操作符后跟一个构造函数来创建的,构造函数本身就是一个函
    数,只不过该函数是出于创建新对象的目的而定义的。
  4.ECMAScript提供了很多原生引用类型(如:ObjectArrayFunction等),以便开发人员用以实现常见的计算
    任务。
  5.js中的函数实际上是对象,每个函数都是Function类型的实例,而且都与其他引用类型一样具有属性和方法。
    由于函数是对象,因此函数名实际上也是一个指向函数对象的指针,不会与某个函数绑定。如:
    function sum(num1,num2){
        return num1 + num2;
    } 
    这与使用函数表达式定义函数的方法几乎相差无几:
    var sum = function(num1,num2){
        return num1 + num2;
    }
2.基本包装类型:
  1.为了便于操作基本数据类型值,js还提供了3个特殊的引用类型:BooleanNumberString。这些类型与其他引
    用类型相似,但有与各自的基本数据类型相应的特殊行为。
  2.实际上,每当读取一个基本类型的时候,后台就会创建一个对应的基本包装类型的对象,从而让我们可以能够调用一
    些方法来操作这些数据。如下:
    var s1 = "hello,world";
    var s2 = s1.substring(2);
    尽管如我们所愿,基本类型调用了方法,但是基本类型不是对象,因而从逻辑上讲他们不应该具有方法。 
  3.其实,为了实现这种直观的操作,后台已经自动完成了一系列的处理。当第二行代码访问s1时,访问过程处于一种读
    取模式,也就是从内存中读取这个字符串的值,而在读取模式中访问字符串时,后台都会自动完成以下处理:
    a.创建String类型的一个实例;
    b.在实例上调用指定的方法;
    c.销毁这个实例。
    经过处理,基本的字符串就变得跟对象一样了。
  4.引用类型与基本包装类型的主要区别就是对象的生存期。使用new创建的引用类型实例,在执行流离开当前作用域之
    前都一直保存在内存中,而自动创建的基本包装类型的对象,只存在一行代码的执行瞬间,然后立即被销毁。这也意
    味着我们不能在运行时为基本类型值添加属性和方法。
3.单体内置对象:
  1.单体内置对象是由ECMAScript实现提供的,不依赖宿主环境的对象,也就是开发人员不必显示地实例化内置对象,
    因为它们已经实例化了。如:GlobalMath。
  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.对于引用类型的变量,==和===只会判断引用的地址是否相同,而不会判断对象具体里属性以及值是否相同。因此,如果两个变量指向相同的对象,则返回true6.javascript引用数据类型是保存在堆内存中的对象,与其它语言不同的是,你不可以直接访问堆内存空间中的位置和操作堆内存空间。只能通过操作对象的在栈内存中的引用地址。所以引用类型的数据,在栈内存中保存的实际上是对象在堆内存中的引用地址。通过这个引用地址可以快速查找到保存在堆内存中的对象
7.一般而言,基本数据类型是有固定数目的字节组成,这些字节可以在解析器的较底层进行操作比如NumberBoolean;而引用数据类型,可以包含任意数目的属性和元素,因此它们无法像基本数据类型那样很容易的操作。由于,引用数据类型的值是会发生变化的,所以通过跟基本数据类型一样的值传递方式,也就没什么意义了,因为会牵涉到大量的内存的复制和比较,效率太低。所以引用数据类型是通过引用传递方式,实际传递的只是对象的一个地址。比如ArrayFunction因为它们都是特殊的对象所以它都是引用类型。另外,引用类型是可以添加属性,基本类型虽然也可以添加属性,也不会报错,经测试添加完之后却是无法访问的。如下:
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复制的一个副本。下图演示了这种基本数据类型赋值的过程:

image-20210922175641.jpg

案例2:引用类型的复制。

var obj1 = new Object();
var obj2 = obj1;
obj2.name = "我有名字了";
console.log(obj1.name); //我有名字了

分析: 我们声明了一个引用数据类型变量obj1,并把它赋值给了另外一个引用数据类型变量obj2。当我们obj2添加了一个name属性并赋值"我有名字了"。obj1同样拥有了和obj2一样的name属性。说明这两个引用数据类型变量指向同一个堆内存对象。obj1赋值给obj2,实际只是把这个堆内存对象在栈内存的引用地址复制了一份给了obj2,但它们本质上共同指向了同一个堆内存对象。下面我们来演示这个引用数据类型赋值过程:

image-20210922175642.jpg 自然,给obj2添加name属性,实际上是给堆内存中的对象添加了name属性,obj2和obj1在栈内存中保存的只是堆内存对象的引用地址,虽然也是拷贝了一份,但指向的对象却是同一个。故而改变obj2引起了obj1的改变。

6.传递值的时候相同
没有差别。“ECMAScript中所有的函数都是按值传递的”。