深入对象

创建对象

创建对象有三种方式

  1. 利用对象字面量创建对象
1
2
3
const o = {
name: '柯南'
}
  1. 利用new object创建对象
1
2
const o = new Object({ name: '柯南' })
console.log(o) // {name: '柯南'}
  1. 利用构造函数创建对象

构造函数

构造函数是专门用于创建对象的函数,如果一个函数使用 new 关键字调用,那么这个函数就是构造函数

  • 构造函数: 时一种特殊的函数,主要用来初始化对象
  • 使用场景: 常规的{…}语法允许创建一个对象。比如我们创建了柯南的对象,继续创建小兰的对象还需要重新写一遍,此时可以通过构造函数快速创建多个类似的对象
  • 构造函数语法: 大写字母开头命名
  • 实例化执行过程:
    1. 创建新对象
    2. 构造函数this指向新对象
    3. 执行构造函数代码,修改this,添加新的属性
    4. 返回新对象
1
2
3
4
5
6
7
8
9
10
11
12
13
// 定义函数
function foo() {
console.log('通过 new 也能调用函数...');
}
// 调用函数
new foo;
// 创建构造函数
function Ultraman(name) {
this.name = name
}
// 接受创建的对象
const man = new Ultraman('Tiga')
console.log(man) // {name: 'Tiga'}

总结:

  1. 使用 new 关键字调用函数的行为被称为实例化
  2. 实例化构造函数时没有参数时可以省略 ()
  3. 构造函数内部无需写return,返回值即为新创建的对象
  4. 构造函数内部的 return 返回的值无效!
  5. new Object()new Data()也是实例化构造函数

实例成员

通过构造函数创建的对象称为实例对象,实例对象中的属性和方法称为实例成员

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function Person() {
// 构造函数内部的 this 就是实例对象
// 实例对象中动态添加属性
this.name = '小明'
// 实例对象动态添加方法
this.sayHi = function () {
console.log('大家好~')
}
}
// 实例化,p1 是实例对象
// p1 实际就是 构造函数内部的 this
const p1 = new Person()
console.log(p1)
console.log(p1.name) // 访问实例属性
p1.sayHi() // 调用实例方法
  1. 实例对象的属性和方法即为实例成员
  2. 为构造函数传入参数,动态创建结构相同但值不同的对象
  3. 构造函数创建的实例对象彼此独立互不影响

静态成员

在 JavaScript 中底层函数本质上也是对象类型,因此允许直接为函数动态添加属性或方法

构造函数的属性和方法被称为静态成员

1
2
3
4
5
6
7
8
9
10
11
12
13
// 构造函数
function Person(name, age) {
// 省略实例成员
}
// 静态属性
Person.eyes = 2
Person.arms = 2
// 静态方法
Person.walk = function () {
console.log('^_^人都会走路...')
// this 指向 Person
console.log(this.eyes)
}
  1. 构造函数的属性和方法被称为静态成员
  2. 一般公共特征的属性或方法静态成员设置为静态成员
  3. 静态成员方法中的this指向构造函数本身

内置构造函数

在JavaScript当中最主要的数据类型有6种:

基本数据类型

  • 字符串、数值、布尔、undefined、null

引用类型

  • 对象

其实很多基本类型也有专门的构造函数,成为包装类型。

JS中几乎所有的数据都可以基于构造函数创建

引用类型: Object、Array、RegExp、Date等

包装类型: String、Number、Boolean等

Object

Object 是内置的构造函数,用于创建普通对象

1
2
3
4
5
6
7
8
// 通过构造函数创建普通对象
const user = new Object({name: 'kenan', age: 12})
// 字面体方式声明对象
const user = { name: 'kenan', age: 12}
for (let k in user) {
console.log(k) // name age
console.log(user[k]) // kenan 12
}

Object.keys: 获取对象中所有的属性(键)

1
2
3
const user = {name: 'kenan', age: 12}
const arr = Object.keys(user)
console.log(arr) // ['name', 'age']

Object.values: 获取对象中所有的属性值

1
2
3
const user = {name: 'kenan', age: 12}
const arr = Object.values(user)
console.log(arr) // ['kenan', 12]

Object.assign: 常用于对象拷贝

1
2
3
4
5
6
7
8
const user = {name: 'kenan', age: 12}
const obj = {}
Object.assign(obj, user)
console.log(obj) // {name: 'kenan', age: 12}

// 典型用法,给对象添加属性
Object.assign(user, {gender: 'men'})
console.log(user) // {name: 'kenan', age: 12, gender: 'men'}

总结:

  1. 推荐使用字面量方式声明对象,而不是 Object 构造函数
  2. Object.assign 静态方法创建新的对象
  3. Object.keys 静态方法获取对象中所有属性
  4. Object.values 表态方法获取对象中所有属性值

Array

Array是内置的构造函数,用于创建数组

1
2
3
4
const arr = new Array(2, 5, 0)
console.log(arr) // [2, 5, 0]
// 创建数组建议使用字面量创建,不用Array构造函数创建
const list = [2, 5, 0]

数组常见方法:

方法 作用 说明
forEach 遍历数组 不返回,用于不改变值,经常用于查找打印输出值
filter 过滤数组 筛选数组元素,并生成新数组
map 迭代数组 返回新数组,新数组里面的元素是处理之后的值,经常用于处理数据
reduce 累计器 返回函数累计处理的结果,经常用于求和等

reduce方法

作用: reduce 返回函数累计处理的结果,常用于求和等
基本用法: arr.reduce(function(累计值, 当前元素){}, 起始值)
累计值参数:

  1. 如果有起始值,则以起始值为准开始累计,累计值 = 起始值
  2. 如果没有起始值,则累计值以数组的第一个数组元素作为起始值开始累计
  3. 后面每次遍历就会用后面的数组元素累计到 累计值 里面(类似求和里面的sum)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const arr = [1, 5, 8]
// 没有初始值
const total = arr.reduce(function(prev, current) {
return prev + current
})
console.log(total) // 14

// 有初始值
const total = arr.reduce(function(prev, current) {
return prev + current
}, 10)
console.log(total) // 24

// 用箭头函数写法
const total = arr.reduce((prev, current) => prev + current, 20)
console.log(total) // 34

总结:

  1. 推荐使用字面量方式声明数组,而不是使用Array构造函数
  2. 实例方法 forEach 用于遍历数组,替代 for 循环
  3. 实例方法 filter 过滤数组单元值,生成新数组
  4. 实例方法 map 迭代原数组,生成新数组
  5. join :数组元素拼接为字符串,返回字符串
  6. find :查找元素,返回符合测试条件的第一个数组元素值,如果没有符合条件的则返回undefined
  7. every :检测数组所有元素是否都符合指定条件,如果所有元素都通过检测返回true,否则返回false
  8. some :检测数组中的元素是否满足指定条件,如果数组中有元素满足条件返回true,否则false
  9. concat :合并两个数组,返回生成新数组
  10. sort :对原数组单元值排序
  11. splice :删除或替换原数组单元
  12. reverse :反转数组
  13. findIndex :查找元素的索引值

包装类型

在 JavaScript 中的字符串、数值、布尔具有对象的使用特征,如具有属性和方法,如下代码举例:

1
2
3
4
5
6
7
8
// 字符串类型
const str = 'hello world!'
// 统计字符的长度(字符数量)
console.log(str.length)
// 数值类型
const price = 12.345
// 保留两位小数
price.toFixed(2) // 12.34

之所以具有对象特征的原因是字符串、数值、布尔类型数据是 JavaScript 底层使用 Object 构造函数“包装”来的,被称为包装类型

String

String 是内置的构造函数,用于创建字符串

1
2
3
4
5
6
7
// 使用构造函数创建字符串
let str = new String('hello world!');
// 字面量创建字符串
let str2 = '你好,世界!';
// 检测是否属于同一个构造函数
console.log(str.constructor === str2.constructor); // true
console.log(str instanceof String); // false

总结

  1. 实例属性 length 用来获取字符串的长度(重点)
  2. 实例方法 split('分隔符') 用来将字符串拆分成数组(重点)
  3. 实例方法 substring(需要截取的第一个字符的索引[,结束的索引号]) 用于字符串截取(重点)
  4. 实例方法 startsWith(检测字符串[, 检测位置索引号]) 检测是否以某字符开头(重点)
  5. 实例方法 includes(搜索的字符串[, 检测位置索引号]) 判断一个字符串是否包含在另一个字符串中,根据情况返回 truefalse(重点)
  6. 实例方法 toUpperCase 用于将字母转换成大写
  7. 实例方法 toLowerCase 用于将就转换成小写
  8. 实例方法 indexOf 检测是否包含某字符
  9. 实例方法 endsWith 检测是否以某字符结尾
  10. 实例方法 replace 用于替换字符串,支持正则匹配
  11. 实例方法 match 用于查找字符串,支持正则匹配

Number

Number 是内置的构造函数,用于创建数值

1
2
3
4
5
6
7
// 使用构造函数创建数值
let x = new Number('10')
let y = new Number(5)
// 字面量创建数值
let z = 3.14159
// 保留两位小数,四舍五入
console.log(z.toFixed(2)) // 3.14

总结

  1. 推荐使用字面量方式声明数值,而不是 Number 构造函数
  2. 实例方法 toFixed 用于设置保留小数位的长度