简介
在javaScript中,对象是一组无序的相关属性与方法的集合,对象具有对应的特征与行为,前面我们也说过,对象也是javaScript中的一种数据类型
分类
内置对象
内置对象就是ES6标准中定义的对象,在任何的ES的视线中都可以使用,内置对象最大的优点就是帮助我们快速开发。JavaScript的内置对象:
内置对象 | 对象说明 |
---|---|
Arguments | 函数参数集合 |
Array | 数组 |
Boolean | 布尔对象 |
Math | 数学对象 |
Date | 日期时间 |
Error | 异常对象 |
Function | 函数构造器 |
Number | 数值对象 |
Object | 基础对象 |
RegExp | 正则表达式对象 |
String | 字符串对象 |
宿主对象
所谓的宿主对象就是由js运行环境提供的对象,目前主要是指浏览器提供的对象,比如BOM, DOM
自定义的对象
简单来说就是我们代码定义的对象,通过 new 关键字创建出来的对象实例,都是属于对象类型。
为什么使用自定义对象
保存一个值时,可以使用变量,保存多个值(一组值)时,可以使用数组,如果用 JS 中的自定义对象来表达,结构会更清晰。如下:
const person = {
name: 'tom',
age: 16,
sex: '女',
favor: ['瑜伽', '看书'],
sayHi: function () {
console.log('hello');
},
};
由此可见,自定义对象里面的属性均是键值对(key: value),表示属性和值的映射关系:
-
键/属性:属性名。
-
值:属性值,可以是任意类型的值(数字类型、字符串类型、布尔类型,函数类型等)。
自定义对象的语法
语法如下:
const obj = {
key: value,
key: value,
key: value,
};
key 和 value 之间用冒号分隔,每组 key:vaue 之间用逗号分隔,最后一对 key:value 的末尾可以写逗号,也可以不写逗号。
问:对象的属性名是否需要加引号?
答:如果属性名不符合 JS 标识符的命名规范,则需要用引号包裹。比如:
const person = {
'my-name': 'tom',
};
补充:其实,JS 的内置对象、宿主对象,底层也是通过自定义对象的形式(也就是键值对的形式)进行封装的。
对象的方法
对象的属性值可以是任意的数据类型,也可以是个函数(也称之为方法)。换而言之,如果对象的属性值是函数,则这个函数可被称之为对象的“方法”。
const obj = new Object();
obj.sayName = function () {
console.log('hello');
};
// 没加括号,就是获取方法
console.log(obj.sayName);
console.log('-----------');
// 加了括号,就是调用方法。即:执行函数内容,并执行函数体的内容
console.log(obj.sayName());
对象的属性值
举例:
//创建对象 obj1
var obj1 = new Object();
obj1.test = undefined;
//创建对象 obj2
var obj2 = new Object();
obj2.name = 'hello';
//将整个 obj2 对象,设置为 obj1 的属性
obj1.test = obj2;
console.log(obj1.test.name); //hello
传值和传址的区别
对象保存在哪里
1、基本数据类型的值直接保存在栈内存中,变量与变量之间是独立的,值与值之间是独立的,修改一个变量不会影响其他的变量。
2、对象是保存到堆内存中的,每创建一个新的对象,就会在堆内存中开辟出一个新的空间。变量保存的是对象的内存地址(对象的引用)。换而言之,对象的值是保存在堆内存中的,而对象的引用(即变量)是保存在栈内存中的。
如果两个变量保存的是同一个对象引用,当一个通过一个变量修改属性时,另一个也会受到影响。这句话很重要,我们来看看下面的例子。
传值
代码举例:
let a = 1;
let b = a; // 将 a 赋值给 b
b = 2; // 修改 b 的值
console.log(a) // 1
console.log(b) // 2
上方代码中,当我修改 b 的值之后,a 的值并不会发生改变。这个大家都知道。我们继续往下看。
传址
代码举例:
var obj1 = new Object();
obj1.name = 'tom';
var obj2 = obj1; // 将 obj1 的地址赋值给 obj2。从此, obj1 和 obj2 指向了同一个堆内存空间
//修改obj2的name属性
obj2.name = 'jack';
console.log(obj1.name) // jack
console.log(obj2.name) // jack
上面的代码中,当我修改 obj2 的 name 属性后,会发现,obj1 的 name 属性也会被修改。因为 obj1 和 obj2 指向的是堆内存中的同一个地址。
这个例子要尤其注意,实战开发中,很容易忽略。
对于引用类型的数据,赋值相当于地址拷贝,a、b 指向了同一个堆内存地址。所以改了 b,a 也会变;本质上 a、b 就是一个东西。
如果你打算把引用类型 A 的值赋值给 B,让 A 和 B 相互不受影响的话,可以通过 Object.assign() 来复制对象。效果如下:
var obj1 = { name: '孙悟空' };
// 复制对象:把 obj1 赋值给 obj3。两者之间互不影响
var obj3 = Object.assign({}, obj1);
下面我们讲几个常用的内置对象的使用
String
在日常开发中,String 对象(字符串对象)的使用频率是非常高的,需要注意的是:字符串的所有方法,都不会改变原字符串(字符串的不可变性),操作完成后会返回一个新的值
字符串查找
indexOf()
这个方法,是使用频率最高的一个方法。获取字符串指定字符的索引
index = str.indexOf(想要查询的字符串,[起始位置]);
indexOf()
是从前向后查找字符串的位置。同理,lastIndexOf()
是从后向前寻找。
起始位置用来指定查找的起始位置
可以检索一个字符串中是否含有指定内容。如果字符串中含有该内容,则会返回其第一次出现的索引;如果没有找到指定的内容,则返回 -1。
因此可以得出一个重要技巧:
-
如果获取的索引值为 0,说明字符串是以查询的参数为开头的。
-
如果获取的索引值为-1,说明这个字符串中没有指定的内容。
var str= "hello"
console.log(str.indexOf("a")) // -1
console.log(str.indexOf("l")) // 2
console.log(str.lastIndexOf("l")) // 3
console.log(str.indexOf("ll"))- // 2
console.log(str.indexOf("le")) // -1
我们来看一个示例,统计一个字符串中某个字符出现的次数, 用indexOf
var str = "hello, welcome to Europe"
var index = str.indexOf('o')
var num = 0
while (index != -1) {
num++;
index = str.indexOf("o", index+1)
}
console.log("o total occur:"+num) // 4
search()
也可以获取字符串中指定内容的索引但是参数里一般是正则
索引值 = str.search(想要查找的字符串);
索引值 = str.search(正则表达式);
search()
方法里的参数,既可以传字符串,也可以传正则表达式。
解释:可以检索一个字符串中是否含有指定内容。如果字符串中含有该内容,则会返回其第一次出现的索引;如果没有找到指定的内容,则返回 -1。
var str= "hel4lo"
console.log(str.search("a")) // -1
console.log(str.search("l")) // 2
console.log(str.search("l4l"))- // 2
console.log(str.search("le")) // -1
console.log(str.search(/4/)) // 3
includes()
判断字符串是否包含指定字符
布尔值 = str.includes(想要查找的字符串, [起始位置]);
判断一个字符串中是否含有指定内容。如果字符串中含有该内容,则会返回 true;否则返回 false。
参数中的 起始位置:如果不指定,则默认为0;如果指定,则规定了检索的起始位置。
var str= "hel4lo"
console.log(str.includes("a")) // false
console.log(str.includes("l")) // true
console.log(str.includes("l4l"))- // true
console.log(str.includes("le")) // false
stratsWith()
判断字符串是否是以指定字符开头
布尔值 = str.startsWith(想要查找的内容, [position]);
判断一个字符串是否以指定的子字符串开头。如果是,则返回 true;否则返回 false。
参数中的position:
-
如果不指定,则默认为0。
-
如果指定,则规定了检索的起始位置。检索的范围包括:这个指定位置开始,直到字符串的末尾。即:[position, str.length)
var str= "hel4lo"
console.log(str.startsWith("a")) // false
console.log(str.startsWith("h")) // true
console.log(str.startsWith("l",2)) // true
endsWith()
判断字符串是否是以指定字符结尾
布尔值 = str.endsWith(想要查找的内容, [position]);
判断一个字符串是否以指定的子字符串结尾。如果是,则返回 true;否则返回 false。
参数中的position:
-
如果不指定,则默认为 str.length。
-
如果指定,则规定了检索的结束位置。检索的范围包括:从第一个字符串开始,直到这个指定的位置。即:[0, position)
-
或者你可以这样简单理解:endsWith() 方法里的position,表示检索的长度。
注意:startsWith() 和 endsWith()这两个方法,他们的 position 的含义是不同的,请仔细区分。
var str= "hel4lo"
console.log(str.endsWith("l")) // false
console.log(str.endsWith("o")) // true
console.log(str.endsWith("l",3)) // true
获取指定位置的字符
charAt(index)/str[index]
字符 = str.charAt(index);
返回字符串指定位置的字符。这里的 str.charAt(index)
和str[index]
的效果是一样的。
注意:字符串中第一个字符的下标是 0。如果参数 index 不在 [0, string.length) 之间,该方法将返回一个空字符串。
var str= "hel4lo"
console.log(str.charAt(2)) // l
console.log(str[2]) // l
console.log(str.charAt(100)) //
console.log(str[100]) // undefined
charCodeAt(index)
字符 = str.charCodeAt(index);
返回字符串指定位置的字符的 Unicode 编码。不会修改原字符串。
str.fromCharCode()根据字符的 Unicode 编码获取字符。
在实际应用中,通过这个方法,我们可以判断用户按下了哪个按键。
字符串截取
slice()
新字符串 = str.slice(开始索引, 结束索引); //两个参数都是索引值。包左不包右。
从字符串中截取指定的内容。不会修改原字符串,而是将截取到的内容返回。
注意:上面的参数,包左不包右。参数举例如下:
-
(2, 5)
截取时,包左不包右。 -
(2)
表示从指定的索引位置开始,截取到最后。 -
(-3)
表示从倒数第三个开始,截取到最后。 -
(1, -1)
表示从第一个截取到倒数第一个。 -
(5, 2)
表示前面的大,后面的小,返回值为空。
substring()
新字符串 = str.substring(开始索引, 结束索引); //两个参数都是索引值。包左不包右。
从字符串中截取指定的内容。和slice()
类似。
substring()
和slice()
是类似的。但不同之处在于:
-
substring()
不能接受负值作为参数。如果传递了一个负值,则默认使用 0。 -
substring()
还会自动调整参数的位置,如果第二个参数小于第一个,则自动交换。比如说,substring(1, 0)
相当于截取的是第一个字符。
substr()
字符串 = str.substr(开始索引, 截取的长度);
从字符串中截取指定的内容。不会修改原字符串,而是将截取到的内容返回。
注意,这个方法的第二个参数截取的长度,不是结束索引。
参数举例:
-
(2,4)
从索引值为 2 的字符开始,截取 4 个字符。 -
(1)
从指定位置开始,截取到最后。 -
(-3)
从倒数第几个开始,截取到最后。
备注:ECMAscript 没有对 substr()
方法进行标准化,因此不建议使用它。
字符串拼接
通常我们可以使用+拼接两个字符串,这里我们使用concat拼接字符串
新字符串 = str1.concat(str2); //连接两个字符串
字符串的连接。
这种方法基本不用,直接把两个字符串相加就好。
是的,你会发现,数组中也有concat()
方法,用于数组的连接。这个方法在数组中用得挺多的。
字符串分割
字符串分割之后会生成一个数组
新的数组 = str.split(分隔符);
通过指定的分隔符,将一个字符串拆分成一个数组。不会改变原字符串。
备注:split()
这个方法在实际开发中用得非常多。一般来说,从接口拿到的 json 数据中,经常会收到类似于"q, i, a, n"
这样的字符串,前端需要将这个字符串拆分成['q', 'i', 'a', 'n']
数组,这个时候split()
方法就派上用场了。
var str= "hello tom welcome"
console.log(str.split(" ")) // [ 'hello', 'tom', 'welcome' ]
字符串替换
新的字符串 = str.replace(被替换的子串,新的子串);
将字符串中的指定内容,替换为新的内容并返回。不会修改原字符串。
注意:这个方法,默认只会替换第一个被匹配到的字符。如果要全局替换,需要使用正则。
代码举例:
//replace()方法:替换
var str2 = 'Today is fine day,today is fine day !';
console.log(str2);
console.log(str2.replace('today', 'tomorrow')); //只能替换第一个today
console.log(str2.replace(/today/gi, 'tomorrow')); //这里用到了正则,才能替换所有的today
字符串重复
newStr = str.repeat(重复的次数);
将字符串重复指定的次数。会返回新的值,不会修改原字符串。
字符串清洗
trim()
:去除字符串前后的空白。
大小写转化
toLowerCase() toUpperCase()
Math
数字也是我们开发中经常使用的一种数据,下面简单介绍一下常用的是方法
Math 和其他的对象不同,它不是一个构造函数,不需要创建对象。所以我们不需要 通过 new 来调用,而是直接使用里面的属性和方法即可。
Math属于一个工具类,里面封装了数学运算相关的属性和方法。如下:
方法 | 描述 | 备注 |
---|---|---|
Math.PI | 圆周率 | Math对象的属性 |
Math.abs() | 返回绝对值 | |
Math.random() | 生成0-1之间的随机浮点数 | 取值范围是 [0,1) |
Math.floor() | 向下取整(往小取值) | |
Math.ceil() | 向上取整(往大取值) | |
Math.round() | 四舍五入取整(正数四舍五入,负数五舍六入) | |
Math.max(x, y, z) | 返回多个数中的最大值 | |
Math.min(x, y, z) | 返回多个数中的最小值 | |
Math.pow(x,y) | 乘方:返回 x 的 y 次幂 | |
Math.sqrt() | 开方:对一个数进行开方运算 |
布尔值 = Number.isInteger(数字); //判断是否为整数
字符串 = myNum.toFixed(num); // 将数字 myNum 的小数点后面保留 num 位小数(四舍五入),并返回。不会改变原数字。注意,返回结果是字符串
Date
Date 对象在实际开发中,使用得很频繁,且容易在细节地方出错,需要引起重视,内置对象 Date 用来处理日期和时间。需要注意的是:与 Math 对象不同,Date 对象是一个构造函数** ,需要先实例化后才能使用。
创建Date对象
创建Date对象有两种写法:
-
写法一:如果Date()不写参数,就返回当前时间对象
-
写法二:如果Date()里面写参数,就返回括号里输入的时间对象
日期格式转化
上一段内容里,我们获取到了 Date 对象,但这个对象,打印出来的结果并不是特别直观。
如果我们需要获取日期的指定部分,就需要用到 Date对象自带的方法。
获取了日期指定的部分之后,我们就可以让日期按照指定的格式,进行展示(即日期的格式化)。比如说,我期望能以 2020-02-02 19:30:59
这种格式进行展示。
在这之前,我们先来看看 Date 对象有哪些方法。
Date对象的方法
Date对象 有如下方法,可以获取日期和时间的指定部分:
方法名 | 含义 | 备注 |
---|---|---|
getFullYear() | 获取年份 | |
getMonth() | 获取月: 0-11 | 0代表一月 |
getDate() | 获取日:1-31 | 获取的是几号 |
getDay() | 获取星期:0-6 | 0代表周日,1代表周一 |
getHours() | 获取小时:0-23 | |
getMinutes() | 获取分钟:0-59 | |
getSeconds() | 获取秒:0-59 | |
getMilliseconds() | 获取毫秒 | 1s = 1000ms |
var d1 = new Date();
console.log(d1) // 2024-04-30T02:07:56.746Z
console.log(d1.getFullYear()) // 2024
console.log(d1.getMonth()) // 3
console.log(d1.getDate()) // 30
console.log(d1.getDay()) // 2
console.log(d1.getHours()) // 10
console.log(d1.getMinutes()) // 7
console.log(d1.getTime()) //1714442876746
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通