一、Object 构造函数 - 模式

缺点:创建时语句太多

  1. let obj = new Object();
  2. obj.name = '张三';
  3. obj.age = 11;

二、对象字面量 - 模式

优点:创建时,语句只有一行
缺点:多次创建时,存在代码冗余

  1. let obj1 = {
  2. name: '张三',
  3. age: 11
  4. }
  5. // 多次创建,代码冗余
  6. let obj1 = {
  7. name: '李四',
  8. age: 12
  9. }

三、工厂模式

优点:重复创建时,避免代码冗余
缺点:无法区分类型

  1. function Student() {
  2. let obj = {
  3. name: '张三',
  4. age: 12
  5. }
  6. return obj;
  7. }
  8. function Teacher() {
  9. let obj2 = {
  10. name: '王老五',
  11. school: '数据学院'
  12. }
  13. return obj2;
  14. }
  15. let stu = Student();
  16. let tea = Teacher();
  17. console.log(stu instanceof Student); // false
  18. 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);

输出结果如下
432D5D28-B932-4DB7-8408-EB9660E91E87_4_5005_c.jpeg
注意: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);

输出结果如下
2DD0665E-D605-4795-9021-E89D79E04BB4_4_5005_c.jpeg