JavaScript初階(六)-------- 繼承發展史、命名空間
繼承發展史
繼承發展史一共有四種形式,接下來讓我們看看。
1.傳統形式
Fir.prototype.lastName = "stg"; function Fir() { this.age = 25; } var fir = new Fir(); Foo.prototype = fir; function Foo() { } var foo = new Foo(); Person.prototype = foo; function Person() { }
從代碼中我們可以看出代碼看起來很繁瑣,不美觀,而且繼承起來很麻煩,所以這種形式一開始就out了。
缺點:過多的繼承了沒用的屬性。
2.借助構造函數
function Person1(name,age){ this.name = name; this.age = age; } function Person2(name,age){ var pObj = Object.create(Person2.prototype); Person1.call(pObj,name,age); return pObj; } var person = new Person2(‘stg‘,23);
這種方式本質上不叫繼承,因為他是借用call和構造函數,把構造函數Person的this指向改變為自己而已,而且訪問不了原型的原型。
缺點:不能繼承借用構造函數的原型,每次構造函數都要多走一個函數。
3.共享原型
function inherit(origin,target){ target.prototype = origin.prototype; } Person.prototype.lastName = "xiaoming"; function Person(){ }; function Son(){ } inherit(Person,Son);
缺點:不能隨意改動自己的原型。
4.聖杯模式
由於第三種方式中出現的不足,所以我會在中間加一個中間層作為過渡,這也就出現了第四種繼承形式-------聖杯模式。
function inherit(Origin,Target){ function Func() { }; Func.prototype = Origin.prototype; Target.prototype = new Func(); } Person.prototype.lastName = "hhh"; function Person () { } function Son() { } inhert(Person, Son);
因為第三種形式中Person和Son的原型都是指向同一個原型,所以改變Person的原型就會是Son的原型發生改變,這裏我們加入一個中間層函數Func過渡,讓它的原型指向Origin的
原型,然後Target的原型繼承它的原型,也就是相當於Target原型繼承Origin的原型,這樣Son改變的時候,Person的原型不會變。再有一點美中不足是,我們知道constructor屬性指向的
是構造這個對象的函數,但是這時候son的constructor指向的是Person,因為Func函數裏面沒有constructor屬性,於是便會隨著原型鏈往上找,於是就找到了Person裏面,這時候我們需
要手動地給son添加一個constructor屬性。
在開發的時候,我們需要一個叫超類(Uber)的東西,用來查詢這個函數究竟是繼承自誰。最終聖杯模式是這樣的:
function inherit(Origin,Target){ function Func() { }; Func.prototype = Origin.prototype; Target.prototype = new Func(); Target.prototype.constructor = Target; Target.prototype.uber = Origin.prototype; }
利用閉包的私有化變量,我們可以將聖杯模式寫的更加高級一點
var inherit = (function () {
var Func = function () { };
return function (origin,target) {
Func.prototype = Origin.prototype;
Target.prototype = new Func() ;
Target.prototype.constructor = Target;
Target.prototype.uber = Origin.prototype;
}
}())//**********function與函數Func產生閉包
命名空間
作用:管理變量,防止汙染全局,適用於模塊化開發
在開發的時候,往往每個人用到的變量不同,團隊開發時就會有變量沖突,我們可以用對象來解決,因為每個對象裏面的東西都是獨立的,互不幹擾。
org = {
person: {
xiaoming : {
age : 20,
sex : "male"
},
xiaozhang : {
age : 22,
sex : "female"
}
}
}
var per1 = org.person.xiaoming.age;
var per2 = org.person.xiaozhang.age;
采用對象來解決變量沖突問題是以前用的方法,現在我們可以用閉包來解決這一問題。
var add = (function () {
var count1 = 1;
var count2 = 0;
function myAdd(num1, num2){
count1 = num1;
count2 = num2;
console.log(count1 + count2);
}
return myAdd(count1,count2);
}())
類似於私有化變量來解決命名沖突,只有在於自己產生閉包的變量才能訪問到。
JavaScript初階(六)-------- 繼承發展史、命名空間