创建对象的几种模式(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属性前可以加一个检测是否存在来判断重写方法。
其余还有寄生构造函数模式和稳妥构造函数模式两种特殊模式。