創(chuàng)建對象
1.工廠模式 用函數(shù)來封裝以特定接口創(chuàng)建對象的細(xì)節(jié).
function createPerson(name,age,job) {
let o=new Object();
o.name=name;
o.age=age;
o.job=job;
o.sayName=function () {
console.log(this.name);
};
return o;
}
let person1=createPerson('Nicholas',29,'Software Enginner');
let person2=createPerson('Greg',27,'Doctor');
person1.sayName();
person2.sayName();
缺點(diǎn) 沒有解決對象識(shí)別的問題(即怎么知道一個(gè)對象的類型);
2構(gòu)造函數(shù)模式
function Person(name,age,job) {
this.name=name;
this.age=age;
this.job=job;
this.sayName=function () {
console.log(this.name);
}// new Function('console.log(this.name)');
}
let p1=new Person('Nicholas',29,'Software Enginner');
p1.sayName();
let p2=new Person('Greg',27,'Doctor');
p2.sayName();
console.log(typeof p1,p1 instanceof Person,p1 instanceof Object);//ojbct true true
console.log(p1.constructor===Person,p2.constructor===Person);
console.log('name:',p1.sayName===p2.sayName,typeof Person.prototype);//false; object
//當(dāng)構(gòu)造函數(shù)使用
let person=new Person('fubao',30,'Software Enginner');
person.sayName();
//
//Person('Greg',27,'Doctor');
//window.sayName();
//在另一個(gè)對象的作用域中調(diào)用
let o=new Object();
Person.call(o,'Kristen',25,'Nurse');
o.sayName();
缺點(diǎn):每個(gè)方法都要在每個(gè)實(shí)例上重新創(chuàng)建一遍.
3:原型模式
創(chuàng)建的每個(gè)函數(shù)都一個(gè)prototype(原型)屬性,它是一個(gè)指針,指向一個(gè)對象,這個(gè)對象的用途是包含可以由特定類型的具有實(shí)例共享的屬性和方法.
優(yōu)點(diǎn):可以讓所有對象的實(shí)例共享它所包含的屬性和方法.
function PersonPT() {
}
PersonPT.prototype.name='Nicholas';
PersonPT.prototype.age=29;
PersonPT.prototype.job='Software Engineer';
PersonPT.prototype.sayName=function () {
console.log(this.name);
};
let pson1=new PersonPT();
pson1.sayName();
let pson2=new PersonPT();
pson2.sayName();
console.log('__proto__是原型對象',pson2.__proto__===PersonPT.prototype);//構(gòu)造函數(shù)的原型對象
console.log('sayName',pson1.sayName===pson2.sayName);//true
console.log(PersonPT.prototype.constructor===PersonPT);
console.log(typeof PersonPT.prototype,PersonPT.prototype instanceof Object);
//通過isPrototypeOf方法來確定實(shí)例的原型是否一樣.
console.log(PersonPT.prototype.isPrototypeOf(pson1));
console.log(PersonPT.prototype.isPrototypeOf(pson2));
//獲得[[Prototype]]
console.log(Object.getPrototypeOf(pson1)===PersonPT.prototype);
console.log(Object.getPrototypeOf(pson1).name);
pson1.name='greg';
console.log(pson1.name,pson2.name);
//delete pson1.name;
//console.log(pson1.name);
//hasOwnProperty()方法可以檢測一個(gè)屬性是存在實(shí)例中,還是存在原型中.
console.log(person1.hasOwnProperty('name'));//true;
delete person1.name;
console.log(person1.hasOwnProperty('name'));//false;
//確定屬性來自原型而不是對象中
function hasPrototypeProperty(object, name) {
return !object.hasOwnProperty(name)&&(name in object);
}
//要取得對象上所有可枚舉的實(shí)例屬性,可使用Object.keys()方法
for(let prop in pson1){
console.log(prop);
}
var keys=Object.keys(PersonPT.prototype);//所有可枚舉的實(shí)例屬性
console.log(keys);
console.log(Object.keys(pson1));
console.log(Object.getOwnPropertyNames(PersonPT.prototype));//所有實(shí)例屬性,是否可枚舉
//3,更簡單的原型語法
function PersonSimple() {
}
PersonSimple.prototype={
//constructor:PersonSimple,
name:'Nicholas',
age:29,
job:'Software Engineer',
sayName:function () {
console.log(this.name);
}
};//constructor屬性不再指向PersonSimple
let friend=new PersonSimple();
console.log(friend instanceof Object);//true;
console.log(friend instanceof PersonSimple);//true
console.log(friend.constructor===PersonSimple);//false;
console.log(friend.constructor===Object);//true;
//原型的動(dòng)態(tài)性
let personSimple=new PersonSimple();
PersonSimple.prototype.sayHI=()=>{
console.log('hi');
};
personSimple.sayHI();//hi
原型模式的缺點(diǎn):a.省略了構(gòu)造函數(shù)傳遞初始化參數(shù).b.共享引用類型會(huì)引起問題.
4.組合使用構(gòu)造函數(shù)模式與原型模式. (推薦使用)
構(gòu)造函數(shù)定義實(shí)例屬性,原型模式用于定義方法與共享的屬性.
優(yōu)點(diǎn):實(shí)例都一份自己實(shí)例屬性副本.同時(shí)共享對方法的引用.節(jié)省內(nèi)存.
function PersonMix(name,age,job){
this.name=name;
this.age=age;
this.job=job;
this.friends=['Shelby','Court'];
}
PersonMix.prototype={
constructor:PersonMix,
sayName:function () {
console.log(this.name);
}
};
let pm1=new PersonMix('Nicholas',29,'Software Engineer');
let pm2=new PersonMix('Greg',27,'Doctor');
pm1.friends.push('Van');
console.log(pm1.friends);
console.log(pm2.friends);
console.log(pm1.sayName===pm2.sayName);
5.動(dòng)態(tài)原型模式.
function PersonDynamic(name,age,job){
this.name=name;
this.age=age;
this.job=job;
if(typeof this.sayName!='function'){//動(dòng)態(tài)體現(xiàn)
PersonDynamic.prototype.sayName=function () {
console.log(this.name);
}
}
}
6.寄生構(gòu)造函數(shù)模式
function PersonCon(name,age,job) {
let o=new Object();
o.name=name;
o.age=age;
o.job=job;
o.sayName=function (){console.log(this.name);};
return o;
}
let f=new PersonCon('fb',30,'SE');
f.sayName();
console.log(f.constructor===PersonCon);
console.log(f.constructor===PersonCon.prototype);
缺點(diǎn):返回對象與構(gòu)造函數(shù)或者與構(gòu)造函數(shù)的原型屬性之間沒有關(guān)系.
7.穩(wěn)妥構(gòu)造函數(shù)模式
穩(wěn)妥對象 指的是沒有公共屬性,而且其方法也不引用this的對象.
function PersonWT(name,age,job) {
let o=new Object();
o.sayName=function () {
console.log(name);
};
return o;
}
let wt=PersonWT('fb',30,'SE');
wt.sayName();