? 前 ?言
?OOP?
JavaScript中OOP——>>>面向對象中的繼承/閉包
?
1.1面向對象的概念
使用一個子類繼承另一個父類,子類可以自動擁有父類的屬性和方法。
?? ?? >>> 繼承的兩方,發生在兩個類之間。
?
1.2JS模擬實現繼承的三種方式:
首先,了解一下call/apply/binb:通過函數名調用方法,強行將函數中的this指向某個對象;
?? ??? ???? call寫法:? func.call(func的this指向的obj,參數1,參數2...);
?? ??? ???? apply寫法:? func.apply(func的this指向的obj,[參數1,參數2...]);
?? ??? ?? ??? binb寫法:? func.binb(func的this指向的obj)(參數1,參數2...);
?? ??? ??
?? ??? ??? call與apply的唯一區別:在于接收func函數的參數方式不同。call采用直接寫多個參數的方式,而apply采用是一個數組封裝所有參數。
?? ??? ?
?? ??? ???? call寫法:? func.call(func的this指向的obj,參數1,參數2...);
?? ??? ???? apply寫法:? func.apply(func的this指向的obj,[參數1,參數2...]);
?? ??? ?? ??? binb寫法:? func.binb(func的this指向的obj)(參數1,參數2...);
?? ??? ??
?? ??? ??? call與apply的唯一區別:在于接收func函數的參數方式不同。call采用直接寫多個參數的方式,而apply采用是一個數組封裝所有參數。
?? ??? ?
① 擴展Object實現繼承
?? ??? ??? 1:定義父類
?? ??? ? ?? ??? ??? ?function Parent(){}
?? ??? ?? ? 2:定義子類
?? ??? ??? ??? ??? ?funtion Son(){}
?? ??? ? ? 3:通過原型給Object對象添加一個擴展方法。
?? ??? ??? ??? ??? ?Object.prototype.customExtend = function(parObj){
?? ??? ??? ??? ???????? for(var i in parObj){
?? ??? ??? ??? ??????? ??? ?// 通過for-in循環,把父類的所有屬性方法,賦值給自己
?? ??? ??? ??? ?????????? ??? ?this[i] = parObj[i];
?? ??? ??? ??? ???????? }
?? ??? ??? ??? ???? }
?? ??? ??? ? 4:子類對象調用擴展方法
?? ??? ??? ??? ? ?? ?Son.customExtend(Parent);
?
① eg:
1 // 1.定義父類 2 function Person(name,age){ 3 this.name = name; 4 this.age = age; 5 this.say = function(){ 6 alert(this.name+":"+this.age); 7 } 8 } 9 // 2.定義子類 10 function Student(no){ 11 this.no = no; 12 this.add = function(a,b){ 13 alert(a+b); 14 } 15 } 16 function Programmer(lang){ 17 this.lang = lang; 18 this.codding = function(){ 19 alert("我愛敲代碼!敲代碼使我快樂!"); 20 } 21 } 22 // 3.通過原型給Object對象添加一個擴展方法。 23 Object.prototype.customExtend = function(parObj){ 24 for(var i in parObj){ 25 // 通過for-in循環,把父類的所有屬性方法,賦值給自己 26 this[i] = parObj[i]; 27 } 28 } 29 30 var p = new Person("小明","18"); 31 var s = new Student("0001"); 32 s.customExtend(p);//現在s繼承了p的所有屬性和方法。 33 console.log(s) 34 35 var pro = new Programmer("JavaScript"); 36 pro.customExtend(p); 37 console.log(pro) 38 39 40 41
?
?
② 使用call/apply/binb.
?? ??? ???????? 1:定義父類
?? ??? ??????? ??? ?funtion Parent(””,””,””){}
?? ??? ??? ??? ?2:定義子類
?? ??? ??? ??? ???? function Son(””,””,””){}
?? ??? ??? ??? ?3:在子類中通過call方法/apply/binb方法去調用父類。
?? ??? ??? ??? ???? function Son(){
?? ??? ??? ??? ??? ??? ?Parent.call(this,””,””,””);// Parent.apply(this,[””,””,””]);//Parent.binb(this)(””,””,””);
?? ??? ??? ??? ???? }
?
② eg:
?
1 function Person(name,age){ 2 this.name = name; 3 this.age = age; 4 this.say = function(){ 5 alert("我叫:"+this.name+";今年:"+this.age+"歲"); 6 } 7 } 8 9 /** 文檔注釋,調用函數時,可以看到注釋內容。 10 * 11 * no:學員編號 12 * stuName:學員姓名 13 * stuAge:學員年齡 14 */ 15 function Student(no,stuName,stuAge){ 16 17 this.no = no; 18 Person.call(this,stuName,stuAge); 19 // 執行上述代碼,相當于將下面的代碼執行一遍。并且把原來Person類的this直接替換為Stundet的this(當實例化Student時的那個對象) 20 21 // this.name = "張三"; 22 // this.age = 14; 23 // this.say = function(){ 24 // alert("我叫:"+this.name+";今年:"+this.age+"歲"); 25 // } 26 } 27 28 var stu = new Student(12,"zhangsan",14); 29 stu.say(); 30 31 console.log(stu) 32 33 //Person("zhangsan","123");
?
?③ 使用原型繼承
?? ??? ???????? 1:定義父類
?? ??? ??????????? function Parent(””,””,””){}
?? ??? ??? ??? ?2:定義子類
?? ??? ??? ??? ??? function Son(””,””,””){}
?? ??? ??? ??? ?3:把在子類對象的原型對象聲明為父類的實例。
?? ??? ??? ??? ??? Son.prototype = new Parent(””,””,””);
?
③ eg:
?
1 function Person(name,age){ 2 this.name = name; 3 this.age = age; 4 this.say = function(){ 5 alert("我叫:"+this.name+";今年:"+this.age+"歲"); 6 } 7 } 8 9 /** 文檔注釋,調用函數時,可以看到注釋內容。 10 * 11 * no:學員編號 12 * stuName:學員姓名 13 * stuAge:學員年齡 14 */ 15 function Student(no){ 16 this.no = no; 17 } 18 19 Student.prototype = new Person("張三",14) 20 21 var stu = new Student(12); 22 23 stu.say(); 24 25 console.log(stu) 26 27 //Person("zhangsan","123");
?
1.3面向對象中的閉包
1、 全局變量:函數外聲明的變量
?? ??? ????? 局部變量:函數內聲明的變量
?? ??? ??
?? ??? ????? 在JS中,函數為唯一的局部作用域,而if、for等其他{}沒有自己的作用域
?? ??? ??
?? ??? ????? 所以,函數外不能訪問局部變量。其實,變量在函數執行完畢以后,占用的內存就被釋放。
?? ??? ??
?? ??? ?? 2、如何訪問函數私有變量?
?? ??? ????? JS中,提供了一種"閉包"的概念:在函數內部,定義一個子函數,可以用子函數訪問父函數的私有變量。執行完操作以后,將子函數通過return返回。
?? ??? ??
?? ??? ??? ? ?? ?function func2(){
?? ??? ??? ??? ??? ?var num = 1;
?? ??? ??? ??? ??? ?function func3(){
?? ??? ??? ??? ??? ??? ?var sum = num+10;
?? ??? ??? ??? ??? ??? ?alert(sum);
?? ??? ??? ??? ??? ?}
?? ??? ??? ??? ??? ?return func3;
?? ??? ??? ??? ?}
?? ??? ??? ??? ?
?? ??? ??? ??? ?var f = func2();
?? ??? ??? ??? ?f();
?? ??? ??
?? ??? ?? 3、閉包的作用:
?? ??? ????? ① 訪問函數的私有變量;
?? ??? ????? ② 讓函數的變量始終存在于內存中,而不被釋放。