一、Object 构造函数 - 模式
缺点:创建时语句太多
let obj = new Object();
obj.name = '张三';
obj.age = 11;
二、对象字面量 - 模式
优点:创建时,语句只有一行
缺点:多次创建时,存在代码冗余
let obj1 = {
name: '张三',
age: 11
}
// 多次创建,代码冗余
let obj1 = {
name: '李四',
age: 12
}
三、工厂模式
优点:重复创建时,避免代码冗余
缺点:无法区分类型
function Student() {
let obj = {
name: '张三',
age: 12
}
return obj;
}
function Teacher() {
let obj2 = {
name: '王老五',
school: '数据学院'
}
return obj2;
}
let stu = Student();
let tea = Teacher();
console.log(stu instanceof Student); // false
console.log(stu instanceof Teacher); // false
如上,显然 stu
理应属于 Student
,然而输出却为 false
四、自定义构造函数模式
优点:可以区分类型
function Student() {
this.name = '张三',
this.age = 12
}
function Teacher() {
this.name = '王老五',
this.school = '数据学院'
}
let stu = new Student();
let tea = new Teacher();
console.log(stu instanceof Student); // true
console.log(stu instanceof Teacher); // false
缺点:存在函数重复,例如
function Student(name, age) {
this.name = name,
this.age = age
this.setName = name => {
this.name = name;
}
}
let stu1 = new Student('张三', 12);
let stu2 = new Student('李四', 14);
console.log(stu1, stu2);
输出结果如下
注意:prototype
实际上是 __proto__
,只是浏览器将其叫成了前者,若输出 stu2.prototype
仍然为 undefined
console.log(stu1.prototype); // undefined
console.log(stu1.__proto__); // 输出与图中的 prototype 相同
显然 setName()
在两个实例中,都是一样的,所以应该让其存储到原型链中去(实例的__proto__
)
五、构造函数 + 原型链组合
优点:重复的函数放到原型中,减少了内存的使用
function Student(name, age) {
this.name = name,
this.age = age
}
Student.prototype.setName = function() { // 此处用箭头函数会导致 this 异常
this.name = name;
}
let stu1 = new Student('张三', 12);
let stu2 = new Student('李四', 14);
stu1.setName('王老五');
console.log(stu1, stu2);
输出结果如下