创建对象的七种方式

72 阅读3分钟

字面量创建

  • 一般使用字面量的形式直接创建对象,但是这种创建方式对于创建大量相似对象的时候,会产生大量的重复代码。但 js和一般的面向对象的语言不同,在 ES6 之前它没有类的概念。但是可以使用函数来进行模拟,从而产生出可复用的对象创建方式

工厂模式

  • 工厂模式的主要工作原理是用函数来封装创建对象的细节,从而通过调用函数来达到复用的目的
  • 缺点:创建出来的对象无法和某个类型联系起来,它只是简单的封装了复用代码,而没有建立起对象和类型间的关系,可读性不好
  • 使用工厂函数创建的对象,instanceof只能用object,instanceof Object 而不能 instanceof Cat
function createCat(name,age,color){
    var cat = new Object();
    cat.name = name;
    cat.color = color;
    cat.age = age;
    cat.favorite = '小鱼干';
    cat.speak = function(){
        console.log('喵~~喵~喵~~~');
    }
    return cat;
}
var myCat = createCat('橘子',1,'orange');

构造函数模式

  • js 中每一个函数都可以作为构造函数,只要一个函数是通过 new 来调用的,那么就可以把它称为构造函数,执行构造函数首先会创建一个对象,然后将对象的原型指向构造函数的 prototype 属性,,然后将执行上下文中的 this 指向这个对象,最后再执行整个函数,如果返回值不是对象,则返回新建的对象
  • 因为 this 的值指向了新建的对象,因此可以使用 this 给对象赋值
  • 优点:所创建的对象和构造函数建立起了联系,因此可以通过原型来识别对象的类型
  • 缺点:造成了不必要的函数对象的创建,因为在 js 中函数也是一个对象,因此如果对象属性中如果包含函数的话,那么每次都会新建一个函数对象,浪费了不必要的内存空间,因为函数是所有的实例都可以通用的
  • myCat instanceof Cat => true
function Cat(name,age,color,favorite){
    this.name = name;
    this.age = age;
    this.color = color;
    this.favorite = favorite;
    this.speak = function(){
       console.log('喵~~喵~喵~~~');
    }
}
var myCat = new Cat('橘子',1,'orange','小鱼干');

原型模式

  • 每一个函数都有一个 prototype属性,这个属性是一个对象,它包含了通过构造函数创建的所有实例 都能共享的属性和方法。因此可以使用原型对象来添加公用属性和方法,从而实现代码的复用
  • 优点:式相对于构造函数模式来说,解决了函数对象的复用问题
  • 缺点:一个是没有办法通过传入参数来初始化值,另一个是如果存在一个引用类型如Array这样的值,那么所有的实例将共享一个对象,一个实例对引用类型值的改变会影响所有的实例
function Cat(name,age,color,favorite){
    this.name = name;
    this.age = age;
    this.color = color;
    this.favorite = favorite;
}
Cat.prototype.weight = 12
var myCat = new Cat('橘子',1,'orange','小鱼干');
myCat.weight

动态原型模式

  • 将原型方法赋值的创建过程移动到了构造函数的内部,通过对属性是否存在的判断,可以实现仅在第一次调用函数时对原型对象赋值一次的效果。这一种方式很好地对上面的混合模式进行了封装
function CreateFn(name,age) {
  this.name = name;
  this.age = age;
  this.arr = [1,2,3];
  if(typeof this.run != "function"){
    console.log("ok");
    CreateFn.prototype.run = function(){
      return "这是原型上的一个 共享方法";
    }
  }
}

var fn1 = new CreateFn("lume",18);
var fn2 = new CreateFn("lume",18);

寄生构造函数模式

  • 这一种模式和工厂模式的实现基本相同,它主要是基于一个已有的类型,在实例化时对实例化的对象进行扩展。这样既不用修改原来的构造函数,也达到了扩展对象的目的
  • 缺点和工厂模式一样,无法实现对象的识别
function Person(name,age) {
    var obj = new Object();
    obj.name = name;
    obj.age = age;
    obj.sayName = function() {
        console.log(this.name);
    }
    return obj;
}
var person1 = new Person('xiao',18);
person1.sayName();

-----------------------------------------------------------------------------2024.5.17每日一题