【面向對象一】從面向過程到面向對象寫函數(shù)方法的進化

[目錄]

  • 面向過程寫函數(shù)
    • 什么是面向過程顺少?什么是面向對象?
    • 【面向過程】和【面向對象】寫函數(shù)的不同
    • 【面向過程】寫函數(shù)的優(yōu)缺點
  • 面向對象寫函數(shù)
    • 單個對象寫函數(shù)
    • 構造函數(shù)寫函數(shù)(類)
    • 給構造函數(shù)的原型對象寫函數(shù)

面向過程寫函數(shù)

什么是面向過程?什么是面向對象嗦玖?

面向過程和面向對象都是一種編程的思想澜掩,也可以理解為一種代碼的組織形式贯涎。面向過程主要關注于解決問題需要一步一步實現(xiàn)的過程谴麦,而面向對象主要關注于把解決的不同問題分給不同的對象管理蠢沿,面向對象不關注于解決問題的步驟,只關注于解決問題的對象匾效。

面向過程和面向對象寫函數(shù)的不同

  1. 面向對象是相對于面向過程發(fā)展來的舷蟀;
  2. 面向過程是在代碼量比較少、功能簡單的場景中適用面哼;面向過程一般適用于項目規(guī)則較大野宜,代碼量較多;
  3. 面向過程所有的事情都是需要我們自己來完成的魔策,親歷親為匈子;面向對象是完成一件事情,只需要找到某個對象闯袒,讓它幫我們完成即可旬牲;
  4. 面向過程中我們處于執(zhí)行者的角色;面向對象中我們處于一個調度者的角色搁吓;
  5. 面向過程的方式要比面向對象的方式代碼執(zhí)行效率高原茅;但是面向對象對于大型項目來說,有利于多人合作開發(fā)堕仔、項目代碼的維護和更新迭代

以js和jq為例進行以下簡單分析:

//js面向過程實現(xiàn)一個將一個標簽添加到頁面中的一個功能
//第一步:創(chuàng)建一個p標簽
var p = document.createElement('p');
//第二步: 用最原始的方式創(chuàng)建一個文本節(jié)點
var txt = document.createTextNode('creat TEXT');
//第三步:將文本節(jié)點添加到p標簽中
p.appendChild(txt);
//ps:這個方法我們平時不常用擂橘,因為我們經(jīng)常使用innerText方法,可以看作innerText中封裝了createTextNode方法

//第四步:將p標簽添加到頁面中去
document.body.appendChild(p);

//jq是面向對象編程的
//找到jq對象摩骨,使用jq對象的append方法
$('body').append('<p>create TEXT</p>');

【面向過程】寫函數(shù)的優(yōu)缺點

  • 優(yōu)點:面向過程的方式要比面向對象的方式代碼執(zhí)行效率高通贞,簡單易懂,沒有復雜的邏輯結構恼五。
  • 缺點:不利于合作開發(fā)昌罩,不利于代碼的維護和擴展。最重要的是會造成嚴重的全局污染灾馒。

寫方法我們一般會經(jīng)歷下面的幾個步驟:

//一開始我們寫函數(shù)都是這樣聲明的
function checkName(){
  console.log("name");
}
function checkEmail(){
  console.log("email");
}
function checkPassword(){
  console.log("key");
}

//同理茎用,也可以使用變量聲明
var checkName = function(){
  console.log("name");
}
var checkEmail = function(){
  console.log("email");
}
var checkPassword = function(){
  console.log("key");
}

//調用方式
checkName();//name

這兩種方式效果都是一樣的,但是這樣聲明了3個全局變量睬罗。全局污染很容易造成命名沖突的問題轨功,聲明全局變量就會有定義了相同的方法,后面的就把原來的進行覆蓋了容达。

比如:

function happy(){
  console.log("hello!");
}

function happy(){
  console.log("world!");
}

happy();
//輸出結果為   world古涧!  后面的方法將前面的覆蓋了,導致前面的不能使用

不僅如此花盐,全局污染 的問題是開發(fā)中值得關注的問題羡滑。

所以我們使用一個對象菇爪,對象有自己的屬性和方法,如果我們要訪問它的屬性和方法柒昏,訪問這個對象點出來屬性和方法就可以了凳宙,所以我們可以創(chuàng)建一個對象,然后把方法放在里面:

var CheckObj = {
  checkName:function(){
    console.log("name");
  },
  checkEmail:function(){
    console.log("email");
  },
  checkPassword:function(){
    console.log("key");
  }
}

//這樣我們使用的時候就用對象點方法
CheckObj.checkName(); //name

當然還有另一種形式昙楚,因為在js中近速,函數(shù)也是對象
var CheckObj = function(){};
CheckObj.checkName = function(){
  console.log("name");
}
CheckObj.checkEmail = function(){
  console.log("email");
}
CheckObj.checkPassword = function(){
  console.log("key");
}

//使用的方式還是和以前是一樣的
CheckObj.checkName(); //name

這樣雖然可以滿足我的需求诈嘿,但是當別人想用我寫的方法時就麻煩了堪旧。因為這個對象不能復制,或者說在new一個實例對象出來的時候奖亚,并不能去繼承這些方法淳梦。

所以要想使用這些方法,就要寫到一個函數(shù)對象(構造函數(shù))中:

var CheckObj = function(){
  return {
    checkName : function(){
      console.log("name");
    },
    checkEmail : function(){
      console.log("email");
    },
    checkPassword : function(){
      console.log("key");
    }
  }
}
//這樣寫的原理是昔字,每次在調用這個函數(shù)的時候爆袍,都把對象返回出來,每次調用這個函數(shù)就返回一個新的對象作郭。
//這樣在執(zhí)行的是CheckObj,但實際上返回了一個新的對象陨囊。這樣使用的時候就互不影響了。

var user = CheckObj();
user.checkName(); //name
//new 也可以繼承了夹攒,但是一般不這么寫
var user1 = new CheckObj();
user1.checkEmail();  //name

雖然這個創(chuàng)建了新的對象完成了我們的需求蜘醋,但是他不是一個真正意義上類的創(chuàng)建方式,并且上面創(chuàng)建的user和CheckObj沒有任何的關系

所以需要進行改造:

var CheckObj = function(){
  this.checkName = function(){
    console.log("name");
  }
  this.checkEmail = function(){
    console.log("email");
  }
  this.checkPassword = function(){
    console.log("key");
  }
}

//這樣就是一個類了咏尝,也是我們說的構造函數(shù),下面的user就是這個構造函數(shù)的實例對象压语,每一個new出來的實例對象都繼承了CheckObj的屬性和方法
var user = new CheckObj();
user.checkName();  //name

我們將所有的方法放到函數(shù)的內部,通過this定義编检,每一個實例對象創(chuàng)建的時候都會對類的this上的屬性進行復制(這種復制是一種深拷貝的復制)胎食。所以這些新創(chuàng)建的對象都有一套自己的方法,驗證如下:

var user = new CheckObj();
user.checkName(); //name
user.checkEmail = function(){
                    console.log("happy")
                  } //對user的checkEmail方法重新進行聲明
var user1 = new CheckObj();
user1.checkEmail(); //email
user.checkEmail(); //happy
//由此可以看出允懂,修改其中一個實例對象的方法的時候厕怜,并沒有影響原來的方法,復制是深拷貝的蕾总。

深拷貝的話酣倾,有時候會造成不必要的消耗,以為會復制很多的相同的對象

解決的辦法就是將這些方法都放到這個構造函數(shù)的原型對象上去:

var CheckObj = function(){};
CheckObj.prototype.checkName = function(){
  console.log("name");
}
CheckObj.prototype.checkEmail = function(){
  console.log("email");
}
CheckObj.prototype.checkPassword = function(){
  console.log("key");
}
//簡潔一點也可以這么寫
CheckObj.prototype = {
  checkName : function(){
    console.log("name");
  },
  checkEmail : function(){
    console.log("email");
  },
  checkPassword : function(){
    console.log("key");
  }
}

//這樣創(chuàng)建出來的對象所擁有的方法就是一個了谤专,因為它們都要到這個對象的原型鏈上去尋找其原型對象的方法躁锡。

寫個例子明白一下:

var Happy = function(){};
Happy.prototype = {
  hello : function(){
    console.log("hello");
  },
  world : function(){
    console.log("world");
  }
}
var happy = new Happy();
var unHappy = new Happy();
happy.hello(); // hello
unHappy.hello(); //hello
Happy.prototype.hello = function(){
  console.log("heheda");
}
happy.hello(); //heheda  這說明剛才那個方法把前面的原型對象里面的方法覆蓋掉了,所以進行不要混用置侍。
unHappy.hello(); //heheda
//這樣也可以說明了映之,happy和unHappy用的是一個方法

上面的聲明拦焚,如果要進行函數(shù)的調用,會連續(xù)寫很多次杠输,可以進行修改赎败,鏈式調用

var CheckObj = function(){};
CheckObj.prototype = {
  checkName : function(){
    console.log("name");
    return this;
  },
  checkEmail : function(){
    console.log("email");
    return this;
  },
  checkPassword : function(){
    console.log("key");
    return this;
  }
}

//使用
var check = new CheckObj();
check.checkName().checkEmail().checkPassword();  //name  email  key

上面基本上就是面向對象的一種方式,下面是更高級的

prototype.js

是一款前端框架蠢甲,里面可以封裝很多方法僵刮,其最大的特點就是對源生對象的擴展,源生對象有什么鹦牛?Function,Array,Object

在原型鏈中搞糕,每一個function 都是由Function對象new出來的,所以如果把方法寫到Function的原型對象中曼追,那么只要是函數(shù)窍仰,就可以繼承這個方法。上個例子:

//在Function的原型對象上面聲明一個方法
Function.prototype.checkEmail = function(){
  console.log("email");
}

//聲明一個函數(shù)礼殊,里面就可以繼承這個方法
var f = function(){};
f.checkEmail();
//或者 
var ff = new Function();
ff.checkEmail();

But!!!!!!這種方式是不允許的驹吮,因為這樣會污染原生對象!!!!!

所以要抽象出一個統(tǒng)一添加方法的功能方法:

Function.prototype.addMethod = function(name,fn){
  this[name] = fn;
  return this;  //返回的是Function所創(chuàng)建出來的實例對象
}

//添加方法(函數(shù)式的調用方式)
var method = function(){};  //或者  var method = new Function();
var m = method.addMethod('checkName',function(){
  console.log("name");
})
console.log(m);  // m接收的是method對象

//所以可以進行鏈式編程
method.addMethod('checkName',function(){
  console.log("name");
  return this;  //this返回的是method函數(shù)對象
}).addMethod('checkEmail',function(){
  console.log("email");
  return this;
}).addMethod('checkPassword',function(){
  console.log("key");
  return this;
})
//調用
methods.checkEmail().checkName();// email  name  之所以可以鏈式編程是因為返回的還是

//-------------------------------------------------------------------
//!!!!!類的調用方式!!!!!
Function.prototype.addMethod = function(name,fn){
  this.prototype[name] = fn;//給Methods的原型對象上面添加方法
  return this;  //返回的是Method,Function創(chuàng)建出來的實例對象
}

var Methods = function(){};  //Function創(chuàng)建出來構造函數(shù)Methods
Methods.addMethod('checkName',function(){//之所以可以鏈式編程是因為返回的還是Methods
  console.log("name");
  return this;   //返回的是m,Methods創(chuàng)建出來的實例對象
}).addMethod('checkEmail',function(){
  console.log("email");
  return this;
});

var m = new Methods(); //Methods構造函數(shù)創(chuàng)建出來實例對象m,m繼承了所有Methods的原型對象的所有方法
m.checkEmail().checkName();// email  name  之所以可以鏈式編程是因為返回的還是m

下面完成作業(yè)

1.鏈式編程的話在函數(shù)體里面記得寫return this

2.給函數(shù)添加多個方法的addMethod方法

Function.prototype.addMethod = function(name,fn){
  this[name] = fn;
  return this;
}

var me = function(){};
me.addMethod("happy",function(a){
  console.log("happy"+a);
  return this;
}).addMethod("unHappy",function(){
  console.log("rain");
  return this;
})

me.happy(" time").unHappy(); //happy time   ,  rain

3.既可以為函數(shù)原型添加方法又可以為其自身添加方法的addMethod的方法

Function.prototype.addMethod = function(name,fn){
  this[name] = fn;
  this.prototype[name] = fn;
  return this;
}

var Me = function(){};
Me.addMethod("happy",function(a){
  console.log("hello" + a);
  return this;
}).addMethod("unHappy",function(){
  console.log("no");
  return this;
})

Me.happy("Me").unHappy();   //helloMe  no
var m = new Me();
m.happy("m").unHappy();    //hellom  no

但是上面那種方法晶伦,調用一次addMethod方法會在函數(shù)自身和原型對象上加兩個相同的方法碟狞,這樣是不科學的。我目前想到的方法是再傳一個參數(shù)婚陪,判斷是給原型對象加還是給自己加族沃,但是我覺得應該是addMethod里面有兩個不同的方法,然后調用的時候調用addMethod中的不同方法就可以了近忙。

下面你們有什么高見竭业,可以題出來探討 ^ ^

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市及舍,隨后出現(xiàn)的幾起案子未辆,更是在濱河造成了極大的恐慌,老刑警劉巖锯玛,帶你破解...
    沈念sama閱讀 212,816評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件咐柜,死亡現(xiàn)場離奇詭異,居然都是意外死亡攘残,警方通過查閱死者的電腦和手機拙友,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,729評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來歼郭,“玉大人遗契,你說我怎么就攤上這事〔≡” “怎么了牍蜂?”我有些...
    開封第一講書人閱讀 158,300評論 0 348
  • 文/不壞的土叔 我叫張陵漾根,是天一觀的道長。 經(jīng)常有香客問我鲫竞,道長辐怕,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,780評論 1 285
  • 正文 為了忘掉前任从绘,我火速辦了婚禮寄疏,結果婚禮上,老公的妹妹穿的比我還像新娘僵井。我一直安慰自己陕截,他們只是感情好,可當我...
    茶點故事閱讀 65,890評論 6 385
  • 文/花漫 我一把揭開白布驹沿。 她就那樣靜靜地躺著艘策,像睡著了一般蹈胡。 火紅的嫁衣襯著肌膚如雪渊季。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,084評論 1 291
  • 那天罚渐,我揣著相機與錄音却汉,去河邊找鬼。 笑死荷并,一個胖子當著我的面吹牛合砂,可吹牛的內容都是我干的。 我是一名探鬼主播源织,決...
    沈念sama閱讀 39,151評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼翩伪,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了谈息?” 一聲冷哼從身側響起缘屹,我...
    開封第一講書人閱讀 37,912評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎侠仇,沒想到半個月后轻姿,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,355評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡逻炊,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,666評論 2 327
  • 正文 我和宋清朗相戀三年互亮,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片余素。...
    茶點故事閱讀 38,809評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡豹休,死狀恐怖,靈堂內的尸體忽然破棺而出桨吊,到底是詐尸還是另有隱情威根,我是刑警寧澤窑眯,帶...
    沈念sama閱讀 34,504評論 4 334
  • 正文 年R本政府宣布,位于F島的核電站医窿,受9級特大地震影響磅甩,放射性物質發(fā)生泄漏。R本人自食惡果不足惜姥卢,卻給世界環(huán)境...
    茶點故事閱讀 40,150評論 3 317
  • 文/蒙蒙 一卷要、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧独榴,春花似錦僧叉、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至症歇,卻和暖如春郎笆,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背忘晤。 一陣腳步聲響...
    開封第一講書人閱讀 32,121評論 1 267
  • 我被黑心中介騙來泰國打工宛蚓, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人设塔。 一個月前我還...
    沈念sama閱讀 46,628評論 2 362
  • 正文 我出身青樓凄吏,卻偏偏與公主長得像,于是被迫代替她去往敵國和親闰蛔。 傳聞我的和親對象是個殘疾皇子痕钢,可洞房花燭夜當晚...
    茶點故事閱讀 43,724評論 2 351

推薦閱讀更多精彩內容

  • 博客內容:什么是面向對象為什么要面向對象面向對象編程的特性和原則理解對象屬性創(chuàng)建對象繼承 什么是面向對象 面向對象...
    _Dot912閱讀 1,405評論 3 12
  • 本章內容 理解對象屬性 理解并創(chuàng)建對象 理解繼承 面向對象語言有一個標志,那就是它們都有類的概念序六,而通過類可以創(chuàng)建...
    悶油瓶小張閱讀 847評論 0 1
  • 昨天因為考試成績任连,我和孩子都很不開心,我告訴自己必須每天交作業(yè)难咕,所以匆忙中發(fā)泄了一下课梳,交了“作業(yè)”;今...
    飴逸閱讀 174評論 0 6
  • 2017年9月21日星期四 今天要好好感賞兒子余佃。中午兒子放學回來暮刃,面帶笑容怖亭,看得出很高興搀擂,我開心地擁抱兒子疟位,問有什...
    若蘭幽香閱讀 235評論 2 2
  • 摘抄: 活在信仰里將有助于減輕我們的壓力偏灿,幫助我們更好地享受人生。堅定信念與信心是擁有信仰的前提国撵,我相信這可以并且...
    芹菜晴空閱讀 286評論 0 1