this
在函數執行時,this 總是指向調用該函數的對象。要判斷 this 的指向,其實就是判斷 this 所在的函數屬于誰。
在《javaScript語言精粹》這本書中,把 this 出現的場景分為四類,簡單的說就是:
- 有對象就指向調用對象
- 沒調用對象就指向全局對象
- 用new構造就指向新對象
- 通過 apply 或 call 或 bind 來改變 this 的所指
繼承模式
圣杯模式實現
Father.prototype.lastname = "C";
Father.prototype.fortune = 1000000;
function Father() {
this.age = 48;
}
function Son() {
this.age = 18;
this.waste = function() {
return this.fortune - 50000;
};
}
var inherit = (function() {
//創建圣杯inherit函數
/* 使用立即函數的原因:函數執行前會進行預編譯,預編譯過程都會產生AO,
如當前案例所示,案例中的立即執行函數(注:以下簡稱立函)執行前預編譯的AO中有buffer函數,
由于當立函執行完畢時會返回一個匿名函數(注:以下簡稱匿函),這個匿函調用了buffer函數,
最終匿函也被賦予到了inherit函數中,導致立函執行前預編譯產生的AO在立函執行完畢后并不會銷毀,
于是buffer函數成為了一個閉包并被一同賦予到了inherit函數中去了,
這樣當在外部使用inherit函數時,將會一直都在使用一個buffer函數,
而不用每次使用時都再新建一個buffer函數 */
return function(targetSon, originFather) {
//讓目標兒子繼承源頭父親
function buffer() {} //buffer函數是一個閉包,僅用做一個緩沖而不做他用
buffer.prototype = originFather.prototype;
//targetSon.prototype = buffer.prototype; /* 不能這么寫,因為這樣寫就相當于對象targetSon、fatherOrigin和buffer共享原型了 */
targetSon.prototype = new buffer(); /* 使對象targetSon試圖修改自身屬性時僅僅是以buffer函數作為對象進行修改,而不會影響到其他對象 */
targetSon.prototype.constructor = targetSon; //令目標兒子記得自己本質是誰
targetSon.prototype.gene = originFather; //令目標兒子記得自己的生父是誰
};
})();
inherit(Son, Father); //調用圣杯inherit函數
Son.prototype.lastname = "X";
var son = new Son();
var father = new Father();
console.log(son.lastname); //控制臺顯示x,敗家兒子成功認賊作父
console.log(
father.lastname
); /* 控制臺顯示c,父親自己的姓并沒有因為敗家兒子
通過改姓來認賊作父的慘痛事實而改變 */
console.log(son.constructor); //控制臺顯示兒子自己的構造函數(本質)
console.log(son.gene); //控制臺顯示兒子自己的生父