JavaScript-对象

简介

在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