创建对象的几种方式
字面量
- 简单粗暴
- 不适合创建多个同样类型的对象的场景
const obj ={ name:"悟空",height:100,age:5000};
工厂函数
-
容易理解
-
失去
血缘关系
,无法简单分辨对象的特征
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>创建对象的几种方式</title>
</head>
<body></body>
<script>
// 1. 字面量(语法糖) {}
let obj1 = { name: "张三", age: 29 };
// 优点: 简单直观
// 2. new Object(): 标准语法 构造函数
let obj2 = new Object({ name: "李四", age: 28 });
// 优点: 区分明确(暂时看不出来)
console.log(obj1, obj2);
// 3. 工厂模式(设置模式: Dessign Model)
// 需求: 创建50个学生对象
// let stu1 = { name: '值1', age: 0 }
// let stu1 = { name: '值1', age: 0 }
// ...
// 特点: 结构一样, 数据不同
// 想办法: 复用结构 --> 函数复用代码, 数据灵活: 参数
function studentFactory(name, age) {
return {
name: name,
age: age,
};
}
let stu1 = studentFactory("张三", 29);
let stu2 = studentFactory("李四", 28);
console.log(stu1, stu2);
// 以上所有方式产生的对象: 都是Object对象: 无法区分
// 有办法进行对象的分类: new Array() 得到一个数组
console.log(new Array());
</script>
</html>
构造函数
- 可以方便的创建对象
- 拥有血缘关系
- 还有后续更多的优势
// 1 声明函数
function createStudent(name, age) {
// 2 通过 this 赋值
this.name = name;
this.age = age;
}
// 3 通过 new 来创建对象
const obj = new createStudent("悟能", 83);
console.log(obj);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>自定义构造函数</title>
</head>
<body></body>
<script>
// 构造函数: 本质是函数, 构造函数的 作用: 创建对象
/*
构造函数的语法要求
1. 定义构造函数
* 为了区分普通函数: 构造函数的名字: 大驼峰 (普通函数小驼峰)
* 构造函数内部: 直接使用 this.属性名 = 属性值 增加属性
* 构造函数不需要return: 自动返回 对象 (跟调用方式有关)
2. 调用构造函数
* new 构造函数名字()
*/
// 自定义构造函数: 学生
function Student(name, age) {
// this直接产生属性
this.name = name;
this.age = age;
// 不需要return: 自动返回值
}
// 调用构造函数: new Student()
const s1 = new Student("周巧", 18);
console.log(s1);
function Teacher(name, age) {
this.name = name;
this.age = age;
}
const t1 = new Teacher("柏松", 29);
console.log(t1);
// 总结
// 自定义构造函数的目的: 实现数据的分类(区别对待)
// 构造函数是由开发者规定的: 使用应该用构造函数的用法
</script>
</html>
构造函数的弊端
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>构造函数-属性值为方法的弊端</title>
</head>
<body></body>
<script>
// 对象内部属性的值: 不限定数据类型
function Student(name, age) {
this.name = name;
this.age = age;
// 学生具有学习能力(方法)
this.study = function () {
// 输出: 谁在学习
console.log(this.name + "正在学习");
};
}
const s1 = new Student("周w", 29);
const s2 = new Student("周q", 18);
// 访问属性
console.log(s1, s2);
console.log(s1.name, s1.age);
// 访问方法
s1.study();
s2.study();
console.log(s1.study == s2.study); // false
// 说明s1.study和s2.study是两个不同的内存地址: 其实事情一样(本质只要一块内存)
// 解决方案: 想办法让不同对象里面的study函数, 指向同一块内存地址
// 函数是一种复合数据类型: 函数的变量传值是引用传递
// 将study函数变成一个全局函数: 属性指向全局函数
function Teacher(name, age) {
this.name = name;
this.age = age;
this.study = study;
}
function study() {
console.log(this.name + "正在学习");
}
const t1 = new Teacher("三儿", 29);
const t2 = new Teacher("四儿", 25);
console.log(t1, t2);
t1.study();
t2.study();
console.log(t1.study === t2.study); // true: 内存地址一样
// 上述方案: 解决了 内存重复占用的问题(只有一份)
// 缺点: 内存是由一个全局变量 study保存的: 容易被污染
study = 1;
console.log(s1.study, s2.study); // 已经存在的对象: 不受影响
const t3 = new Teacher("张三", 40);
console.log(t3.study); // 1 : 不再指向函数
</script>
</html>