今天和你們分享一下近期整理的有關JavaScriptOOP的基礎知識~~~咱們一塊兒來學習一下……編程
JavaScriptOOP基礎數組
1、面向對象編程OOP
一、語言的分類:
面向機器:彙編語言
面向過程:C語言
面向對象:C++,Java,PHP等
二、面向過程和麪向對象
①面向過程:專一於如何去解決一個問題的過程。
編程特色:用一個個函數去實現過程操做,沒有類和對象的概念;
②面向對象:專一於有哪個對象實體去解決這個問題。
編程特色是:出現了一個個的類,由類去生成對象。閉包
2、面向對象的三大特徵
繼承,封裝,多態app
3、類&對象的關係
一、類:一羣有相同特徵(屬性)和行爲(方法)的集合
eg: 人類
屬性:"身高,體重,年齡"
方法:"吃飯,睡覺,敲代碼"
二、對象:從類中,new出的具備肯定屬性值和方法的個體稱爲對象。
eg:張三:屬性:身高:身高178,體重150 方法:說話---我叫張三函數
三、類和對象的關係:
類是抽象的,對象是具體的。
(!類是對象的抽象化,對象是類的具體化!)學習
通俗的來說:
類是一個抽象概念,表示具備相同屬性和行爲的集合。
可是類僅僅表示代表這類羣體具備相同的屬性,可是沒有具體的屬性值。
而對象是對類的屬性進行具體賦值後,而獲得的一個具體的個體;this
eg:人類有身高體重年齡,但不能具體說人類的身高體重具體是多少;而張三是人類的一個具體個體,身高體重等有具體值,則張三就是人類的一個對象。spa
四、使用類和對象的步驟:
①建立一個類(構造函數):
類名,必需要每一個單詞首字母都大寫prototype
function 類名(屬性一){
this.屬性 = 屬性一;
this.方法= function(){}
//this指向誰?即將調用當前構造函數的對象。
}code
②經過類,實例化出一個新的對象;
var obj = new 類名(屬性一Value);
//原構造函數中this,指向新建立的obj對象
obj.方法();調用方法
obj.屬性();調用屬性
實例化對象的時候,會執行構造函數
五、兩個重要屬性:
constructor:返回當前對象的構造函數。(只有對象纔有,返回的是構造函數-類)
>>>zhangsan.constructor == Person
>>>對象的constructor,位於_proto_原型對象上(後續講解)
instanceof:判斷對象是不是某個類的實例
>>>zhangsan instanceof Person true
>>>zhangsan instanceof Object true
>>>Person instanceof Object true(函數也是對象)
六、廣義對象與狹義對象:
廣義對象:除了用字面量聲明的基本數據類型以外,外物皆對象,換句話說,可以添加屬性和方法的變量,就是對象;
var s = "1" ; 不是對象
var s = new String("1") ; 就是對象
狹義對象:只有屬性,方法,除此以外沒有任何東西。
var obj = {}; var obj = new Object();
成員屬性與成員方法
1、成員屬性與成員方法
一、在構造函數中經過this.屬性聲明;或者實例化出對象後,經過"對象.屬性"追加的。
都屬於成員屬性,或成員方法;也叫實例屬性與實例方法。
成員屬性/方法,是屬於實例化出的這個對象。
經過"對象.屬性"調用
2、靜態屬性與靜態方法
二、經過"類名.屬性名","類名.方法名"聲明的變量,稱爲靜態屬性,靜態方法;也叫類屬性、類方法。
類屬性/類方法,是屬於類的(屬於構造函數的)
經過"類名.屬性名"調用
三、成員屬性,是屬於實例化出的對象的,會出如今新對象的屬性上
靜態屬性,是屬於類(構造函數)本身的,不會出如今新對象的屬性上
四、JS對象屬性的刪除:
①對象無需手動刪除,JS
②刪除對象的屬性:delete 對象名.屬性名
五、對象是引用數據類型
也就是說,當new出一個對象時,這個obj變量存儲的其實是對象的地址,在對象賦值時,賦的也是地址。
function Person(){}
var xiaoxi = new Person();//xiaoxi對象實際上存的是地址
var ashu = xiaoxi;//賦值時,實際是將xiaoxi存的地址給了ashu
ashu.name = "阿樹";//阿樹經過地址,修改了地址
console.log(xiaoxi.name);//xiaoxi再經過地址打開對象,實際已經變了
引用數據類型,賦值時傳遞的是引用(地址)---快捷方式
基本數據類型,賦值時傳遞的是數據(值)
3、私有屬性和私有方法
六、在構造函數中,經過var聲明的屬性,成爲私有屬性:
function Person(){var num=1;}
私有屬性的做用域,僅在當前函數有效。對外不公開,即經過對象/類都沒法調用到。
原型與原型鏈
【__proto__與prototype】
一、prototype(函數的原型):函數纔有prototype。
prototype是一個對象,指向了當前構造函數的引用地址。
二、__proto__(對象的原型對象):全部對象都有__proto__屬性。當用構造函數實例化(new)一個對象時,
會將新對象的__proto__屬性,指向構造函數的prototype。
eg:zhangsan.__proto__==Person.prototype √
全部對象最終都會指向Object()的prototype。
【原型鏈】
一、經過構造函數,new出的對象,新對象的__proto__指向構造函數的prototype。
二、全部函數的__proto__指向Function()的prototype。
三、非構造函數new出的對象({} new Object() 對象的prototype)的__proto__指向Object的prototype。
四、Object的__proto__指向Null。
原型屬性與原型方法
【類中屬性與方法的聲明方式】
一、成員屬性、成員方法:
this.name = ""; this.func = function(){}
>>>屬於實例化出的對象的。經過"對象.屬性"調用。
二、靜態屬性、靜態方法:
Person.name = ""; Person.func = function(){}
>>>屬於類(構造函數)的。經過"類名.屬性"調用。
三、私有屬性、私有方法:
在構造函數中,使用var num = 1;聲明
>>>只在構造函數內部能用,在外部沒法經過任何方式訪問。
四、原型屬性、原型方法:
Person.prototype.name = "";
Person.prototype.func = function(){};
>>>寫在了構造函數的prototype上,當使用構造函數實例化對象時,該屬性方法會進入新對象的__proto__上。
也就是說,1/4使用對象可訪問,2使用類名可訪問,3只能在函數的{}內使用。
五、習慣上,咱們會將屬性寫爲成員屬性,而方法寫爲原型方法;
eg:
1 function Person(){ 2 this.name = "zhangsan"; 3 } 4 Person.prototype.say = function(){}
緣由:
①實例化出對象後,全部屬性直接在對象上,全部方法都在__proto__上,很是直觀清晰。
②方法寫到prototype上,要更加節省內存。
③使用for in 循環時,會將對象以及對象原型鏈上的全部屬性和方法打印出來,而方法每每是不須要展現的。
將方法寫到__proto__上,可使用hasOwnProperty將原型上的方法更好的過濾。
④官方都這麼寫。
六、當訪問對象的屬性/方法時,會優先使用對象自有的屬性和方法。
若是沒有找到,便使用__proto__屬性在原型上查找,若是找到便可使用。
可是,當對象自身,以及__proto__上有同名方法,執行對象自身的。
七、能夠經過prototype擴展內置函數的相關方法。
代碼演示:
1 function Person(){ 2 this.name1 = "name1"; //成員屬性 3 this.age = "age1"; 4 this.sex = "男"; 5 this.say = function(){ 6 alert("我是大帥哥!"); 7 } 8 var name2 = "name2";//私有屬性 9 } 10 Person.name3 = "name3";//靜態屬性 11 Person.prototype.name4 = "name4";//原型屬性 12 13 14 Person.prototype.say = function(){ 15 alert("我叫"+this.name1); 16 } 17 18 var zhangsan = new Person(); 19 // zhangsan.say = function(){ 20 // alert("我是大帥哥!"); 21 // } 22 zhangsan.say(); 23 zhangsan.toString(); 24 25 console.log(zhangsan); 26 27 // console.log(zhangsan.name1); 28 // console.log(zhangsan.name2); 29 // console.log(zhangsan.name3); 30 // console.log(zhangsan.name4); 31 // 32 // console.log(s);
能夠經過prototype擴展內置函數的相關方法
代碼演示:
1 Number.prototype.add = function(a){ 2 return this+a 3 } 4 5 var num = new Number(10); 6 console.log(num); 7 alert(num.add(3)); 8 9 /* 10 * 爲Array類添加一個find(val)方法,當一個Array對象調用該方法的時候,若是能找到val值,則返回其下標,不然返回-1。 11 */ 12 Array.prototype.find = function(val){ 13 for (var i = 0; i<this.length;i++) { 14 if(this[i]==val){ 15 return i; 16 } 17 } 18 return -1; 19 } 20 var arr = new Array(1,2,3,4,5); 21 alert(arr.find(1));
位String類添加一個字符串反轉方法
1 String.prototype.fanzhuan = function(){ 2 var arr = this.split(""); 3 arr.reverse(); 4 return arr.join("") 5 } 6 7 8 console.log(str.fanzhuan()); 9 10 11 12 for-in循環 13 14 15 【for-in循環】 16 for-in循環,主要用於遍歷對象。 17 for()中格式:for(keys in obj){} 18 19 keys表示obj對象的每個鍵值對的鍵,因此{}中,使用obj[keys]讀取每一個值; 20 可是,使用for-in循環,不但能遍歷對象自己的屬性和方法。還可以遍歷對象原型鏈上的全部屬性和方法。 21 22 可使用hasOwnProperty判斷一個屬性,是不是對象自身的屬性。 23 obj.hasOwnProperty(keys)==true 表示:keys是對象自身的一個屬性 24 25 代碼演示: 26 // foreach 27 function Person(){ 28 this.name1 = "name11111"; //成員屬性 29 this.age = "age11111"; 30 this.func2 = function(){ 31 console.log("thisFun") 32 } 33 } 34 Person.name3 = "name333333"; 35 Person.prototype.name4 = "name44444"; 36 Person.prototype.func1 = function(){ 37 console.log("prototypeFun") 38 } 39 var zhangsan = new Person(); 40 for(keys in zhangsan){ 41 if(zhangsan.hasOwnProperty(keys)){ //過濾掉原型上的屬性,只打印對象自身屬性 42 console.log(zhangsan[keys]) 43 } 44 }
JS OOP 中的繼承【JS模式實現繼承的三種方式】
【文檔註釋】第一行兩個星號
/**
* ……
*/
調用函數時,能夠看到註釋內容
【JS OOP 中的繼承】
一、使用一個子類繼承另外一個父類,子類能夠自動擁有父類的屬性和方法。
>>>繼承的兩方,發生在兩個類之間。
二、JS模式實現繼承的三種方式:
1)擴展Object實現繼承
①定義父類:function Parent(){}
②定義子類:function Son(){}
③經過原型給Object對象添加一個擴展方法。
1 Object.prototype.customExtend = function(parObj){ 2 for(var i in parObj){ 3 //經過for-in循環,把父類的全部屬性方法,賦值給本身。 4 this[i] = ParObj[i]; 5 } 6 }
④子類對象調用擴展方法
son.customExtend(Parent);
2)使用call和apply
首先,瞭解一下call和apply:經過函數名調用方法,強行將函數中的this指向某個對象;
call寫法:func.call(func的this指向的obj,參數1,參數2...);
apply寫法:func.apply(func的this指向的obj,[參數1,參數2...]);
call與apply的惟一區別:在於接收func函數的參數方式不一樣。call採用直接寫多個參數的方式,而apply採用是一個數組封裝全部參數。
①定義父類 funtion Parent(){}
②定義子類 function Son(){}
③在子類中經過call方法或者apply方法去調用父類。
function Son(){
Parent.call(this,....);
}
3)使用原型繼承
①定義父類function Parent(){}
②定義子類function Son(){}
③把在子類對象的原型對象聲明爲父類的實例。
Son.prototype = new Parent();
閉包
【JS中的做用域】
一、全局變量:函數外聲明的變量
局部變量:函數內聲明的變量
在JS中,函數爲惟一的局部做用域,而if、for等其餘{}沒有本身的做用域
因此,函數外不能訪問局部變量。
其實,變量在函數執行完畢之後,佔用的內存就被釋放。
二、如何訪問函數私有變量?
JS中,提供了一種"閉包"的概念:在函數內部,定義一個子函數,能夠用子函數訪問父函數的私有變量。執行完操做之後,將子函數經過return返回。
1 function func2(){ 2 var num = 1; 3 function func3(){ 4 var sum = num+10; 5 alert(sum); 6 } 7 return func3; 8 } 9 var f = func2(); 10 f();
三、閉包的做用:
① 訪問函數的私有變量;
② 讓函數的變量始終存在於內存中,而不被釋放。
代碼演示:
1 function func1(){ 2 var n = 1; 3 } 4 if(true){ 5 var m = 3; 6 } 7 //alert(m); // 3 8 func1(); 9 //alert(n);// 報錯。函數外不能訪問局部變量。其實,n變量在func1函數執行完畢之後,佔用的內存就被釋放。 10 11 12 /*閉包*/ 13 function func2(){ 14 var num = 1; 15 function func3(){ 16 var sum = num+10; 17 alert(sum); 18 } 19 return func3; 20 } 21 var f = func2(); 22 f(); 23 24 // 循環轉一次,建立一個lis[i].onclick函數。可是,當點擊li執行函數的時候,i已經變爲6,因此不管點擊哪個,i都是6 25 // 循環建立lis[i].onclick的時候, 循環一次,li[i]裏面的i都被賦爲不一樣值;建立了 li[1] li[2] li[3]... 26 // 可是,建立過程當中,並無執行onlick後面的函數,因此函數裏面的i並無賦值,仍是字母i。 27 // 最終,咱們點擊li[1] li[2]...時,onclick函數裏面的i纔會賦值。(但此時,全局變量的i ,已經成爲6 了) 28 var lis = document.getElementsByTagName("li"); 29 for (var i=0;i<lis.length;i++) { 30 lis[i].onclick = function(){ 31 //alert("您/點擊了第"+i+"個li!"); 32 //console.log(lis[i]); 33 //console.log(this); 34 } 35 } 36 37 // 循環轉一次,建立一個自執行函數。 38 // 而自執行函數擁有本身的做用域,因此用函數局部做用域j保存當前的全局變量i值。這樣,建立第一個自執行函數,它的j=1;建立第二個,它的j=2...不一樣函數的j互不干擾。 39 // 這樣,循環轉完之後,至關於建立了6個自執行函數,每一個函數中都有一個不一樣的j變量 40 var lis = document.getElementsByTagName("li"); 41 for (var i=0;i<lis.length;i++) { 42 !function(){ 43 var j = i; 44 lis[j].onclick = function(){ 45 alert("您/點擊了第"+j+"個li!"); 46 //console.log(lis[i]); 47 //console.log(this); 48 } 49 }(); 50 } 51 52 var lis = document.getElementsByTagName("li"); 53 for (var i=0;i<lis.length;i++) { 54 !function(j){ 55 lis[j].onclick = function(){ 56 alert("您/點擊了第"+j+"個li!"); 57 //console.log(lis[i]); 58 //console.log(this); 59 } 60 }(i); 61 }