JS面向?qū)ο笾畡?chuàng)建對象

面向?qū)ο蟮乃枷胫饕且詫ο鬄橹?,將一個問題抽象出具體的對象,并且將抽象出的對象和對象的屬性和方法封裝成一個類。

面向過程就是分析出解決問題所需要的步驟,然后用函數(shù)把這些步驟一步一步實(shí)現(xiàn),使用時候依次調(diào)用函數(shù)。
面向?qū)ο笫前褬?gòu)成問題事務(wù)分解成各個對象,建立對象的目的不是為了完成一個步驟而是為了描述某個事物在整個解決問題的步驟中的行為

面向?qū)ο笏枷氲奶攸c(diǎn)

1.封裝

對于同一個功能,只需要封裝一次,以后再使用,只需要調(diào)用即可,無需重寫,即低耦合高內(nèi)聚。

2.繼承

子類可以繼承父類的屬性和方法

3.多態(tài):重載和重寫

重載:js中沒有真正意義上的重載,但有類似重載的功能,就是傳不同的參數(shù),有不同的返回值;
重寫:子類可以重寫父類的屬性和方法。

創(chuàng)建對象

1.工廠模式

這種模式抽象了具體對象的過程,此方法是用函數(shù)來封裝以特定接口創(chuàng)建對象的細(xì)節(jié)

function createPerson(name,age,sex) {
  var obj = new Object();
  obj.name =  name;
  obj.age = age;
  obj.sex = sex;
  obj.sayName = function () {
    alert(this.name)
  }
  return obj
}
var person1 = createPerson('james',18,'male');
var person2 = createPerson('curry',20,'male')

函數(shù)createPerson()能夠根據(jù)接收的參數(shù)來構(gòu)建一個包含所有必要信息的person對象??梢远啻握{(diào)用這個函數(shù),每次都返回含有三個屬性一個方法的對象。
缺點(diǎn)是無法確定創(chuàng)建對象的類型。應(yīng)為都是Object,沒有區(qū)分度,不能像Date,Array一樣。

2.構(gòu)造函數(shù)模式

javascript中有像Object和Array一樣的原生構(gòu)造函數(shù),除此之外,我們?yōu)槟梢詣?chuàng)建自定義的構(gòu)造函數(shù),從而自定義對象的屬性和方法。
構(gòu)造函數(shù)的命名采用大駝峰式命名

function Person(name,age,sex) {
  this.name = name;
  this.age = age;
  this.sex = sex;
  this.sayName = function (){
    alert(this.name)
  }
}
var person1 = new Person('james',18,'male');
var person2 = new Person('curry',20,'male')

要創(chuàng)建Person的實(shí)例,必須使用new操作符,以這種方式調(diào)用構(gòu)造函數(shù)會經(jīng)歷以下三個步驟:
(1)創(chuàng)建一個this對象
var this = {}
(2)將構(gòu)造函數(shù)的作用域賦值給新對象并執(zhí)行構(gòu)造函數(shù)中那個的代碼
this = { name : name, age : age, sex : sex, sayName : function () {alert(this.name)} }
(3)返回新對象
return this
構(gòu)造函數(shù)方法的主要問題是每個方法都要在每個實(shí)例上重新創(chuàng)建一遍,person1和person2都有sayName()的方法,但兩個方法不是同一個Functon的實(shí)例。說明白些,以這種方式創(chuàng)建函數(shù),會導(dǎo)致不同的作用域鏈和標(biāo)識符解析,但創(chuàng)建Function新實(shí)例的機(jī)制是相同的,因此不同實(shí)例上的同名函數(shù)是不相等的,如下:

console.log(person1.sayname == person2.sayName)  //false
3.原型模式

我們創(chuàng)建的每個函數(shù)都有一個prototype屬性,prototype是通過調(diào)用構(gòu)造函數(shù)創(chuàng)建的實(shí)例的原型對象。使用原型對象可以讓所有對象實(shí)例共享它所包含的屬性和方法。

function Person() {}
Person.prototype.name = 'james';
Person.prototype.age = 18;
Person.prototype.sex = 'male'
Person.prototype.sayName = function () {
  alert(this.name)
}
var person1 = new Person();
person1.sayName()  //'james'
var person2 = new Person();
person2.sayName();  //'james'
alert(person1.sayName == person2.sayName);  //true

前面例子中每添加一個屬性和方法就要敲一遍 Person.prototype。為減少
不必要的輸入,也為了從視覺上更好地封裝原型的功能,更常見的做法是用一個包含所有屬性和方法的
對象字面量來重寫整個原型對象

function Person() {}
Person.prototype, = {
  constructor : Person, 
  name : 'james',
  age : 18,
  sex : 'male',
  sayName : function () {
    alert(this,name)
  }
}

以上代碼特意包含了一個 constructor 屬性,并將它的值設(shè)置為 Person,從而確保了通過該屬
性能夠訪問到適當(dāng)?shù)闹?。contrucor是原型對象的一個默認(rèn)屬性,它指向構(gòu)造函數(shù)。
原型模式也不是沒有缺點(diǎn)。通過例子可以發(fā)現(xiàn)它省略了為構(gòu)造函數(shù)傳遞初始化參數(shù)這一環(huán)節(jié),結(jié)果所有實(shí)例在默認(rèn)情況下都將取得相同的屬性值。雖然這會在某種程度上帶來一些不方便,但還不是原型的最大問題。
原型模式的最大問題是由其共享的本性所導(dǎo)致的。

function Person(){ 
} 
Person.prototype = { 
 constructor: Person, 
 name : "james", 
 age : 218, 
 sex : "male", 
 friends : ['Curry','Amy'], 
 sayName : function () { 
 alert(this.name); 
 } 
}; 
var person1 = new Person(); 
var person2 = new Person(); 
person1.friends.push("Van"); 
alert(person1.friends); //'Curry,Amy,Van'
alert(person2.friends); //'Curry,Amy,Van'
alert(person1.friends === person2.friends); //true 

有一個實(shí)例改變了構(gòu)造函數(shù)原型對象的數(shù)組,其他實(shí)例所引用的構(gòu)造函數(shù)的數(shù)組也會改變。

4.原型+構(gòu)造函數(shù)模式

這種混合模式綜合了原型模式和構(gòu)造函數(shù)模式這兩種模式的優(yōu)點(diǎn)

function Person (name,age,sex) {
  this.name = name;
  this.age = age;
  this.sex = sex
this.friends = ['Curry','Amy']
}
Person.prototype = {
  constructor : Person,
  sayName : function () {
    alert(this.name)
  }
}
var person1 = new Person('James',18,'male');
var person2 = new Person('Rose',20,'male');
person1.friends.push("Van"); 
alert(person1.friends); //"Curry,Amy,Van" 
alert(person2.friends); //"Curry,Amy" 
alert(person1.friends === person2.friends); //false 
alert(person1.sayName === person2.sayName); //true

實(shí)例屬性都是在構(gòu)造函數(shù)中定義的,而由所有實(shí)例共享的屬性 constructor 和方
法 sayName()則是在原型中定義的。而修改了 person1.friends(向其中添加一個新字符串),并不
會影響到 person2.friends,因?yàn)樗鼈兎謩e引用了不同的數(shù)組。
所以我們在構(gòu)造對象的時候,一般是原型模式和構(gòu)造模式組合使用,變化的用構(gòu)造模式 不變的公用的用原型模式,就像上面的這個栗子,屬性用的構(gòu)造函數(shù),因?yàn)橐话悴煌瑢ο髮傩远疾煌椒ㄓ迷湍J?/p>

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容