创建对象的几种模式(js)

1.工厂模式

function createPerson(name,age){
  let o = {};
  o.name = name;
  o.age = age;
  o.sayName = function (){
    console.log(this.name)
  }
  return o
}
let person1 = createPerson("nick", 29);

这种模式无法识别创造对象的类型

2.构造函数模式

function Person(name,age){
  this.name = name;
  this.age = age;
  this.sayName = function (){
    console.log(this.name)
  }
}
let person2 = new Person("Grep", 27);

这种模式问题在于不同的对象使用的相同方法并不全等

let person3 = new Person("Grep2", 28);
console.log(person2.sayName === person3.sayName);//false

3.原型模式

function Person(){}
Person.prototype.name = "Nicholas";
Person.prototype.age = 28;
Person.prototype.sayName = function (){
  console.log(this.name);
}
let person1 = new Person();
let person2 = new Person();
console.log(person1.sayName===person2.sayName)

在实例中修改属性

person1.name = 'Grep';
console.log(person1.name, person2.name);// Grep,Nicholas

可以delete该属性,然后person1.name又能访问到原型的属性了

getPrototypeOf方法和hasOwnProperty方法

console.log(Object.getPrototypeOf(person1)==Person.prototype);//true
console.log(Object.getPrototypeOf(person1).name);//Nicholas

console.log(person1.hasOwnProperty("name"));//true,
console.log(person2.hasOwnProperty("name"));//false,name属性存在于原型中而不是实例

原型模式简单写法

function Person(){}

Person.prototype = {
  name:"Nick",
  age:"29",
  sayName:function (){
    console.log(this.name)
  }
}

这种写法实质上是重写了prototype属性,这样constructor属性不再指向Person函数。这样就只能用instanceof来确定对象的类型

原型是动态的模型,即使你创建实例后修改原型,实例上面也能体现你的修改。这是因为实例中的指针指向原型(但并不指向构造函数),如果你像上面那样在实例化之后再重写prototype属性,那样实例对原型的指针就变了。

给String类型添加一个方法

String.prototype.startsWith = function (text){
  return this.indexOf(text) == 0;
}
let msg = "Hello World!";
console.log(msg.startsWith("Hello"))

4.组合使用构造函数和原型模式

function Person(name, age){
  this.name=name;
  this.age=age;
  this.friends=["a","b"];
}
Person.prototype = {
  constructor:Person,
  sayName:function (){
    console.log(this.name)
  }
}
let person1 = new Person("nick","29");
let person2 = new Person("grep", "27");
person1.friends.push("c");
console.log(person1.friends, person2.friends);
console.log(person1.friends===person2.friends);//false
console.log(person1.sayName===person2.sayName);//true

通常,重写prototype属性前可以加一个检测是否存在来判断重写方法。

其余还有寄生构造函数模式和稳妥构造函数模式两种特殊模式。