前 言編程
學過程序語言的都知道,咱們的程序語言進化是從「面向機器」、到「面向過程」、再到「面向對象」一步步的發展而來。相似於彙編語言這樣的面向機器的語言,隨着時代的發展已經逐漸淘汰;而面向過程的語言也只有C語言老大哥依然堅挺;如今主流的語言(例如Java、C++、PHP等)都是面向對象的語言。 而咱們的JavaScript語言,偏偏介於面向過程與面向對象之間,咱們稱它爲「基於對象」的語言。可是,JS中的OOP依然是咱們學習JS的重要一環,固然像「繼承」「封裝」這樣的面向對象特徵,都是由模擬實現的。今天,咱們就一塊兒來探討一下JS中的面向對象吧!數組
1、OOP基礎知識 |
面向對象編程(OOP) 思惟導圖函數
一、類:學習
一類具備相同的特徵(屬性)和行爲(方法)的集合。
eg:人類--> 屬性:身高、性別; 方法:吃飯、說話
二、對象:this
從類中拿出具備肯定屬性值和方法的個體。
eg:張三--> 屬性:身高:170、 體重;50kg; 方法: 說話-->我叫張三,身高170
三、類和對象的關係
類是抽象的,對象是具體的。 (類是對象的抽象化,對象是類的具體化)
類是一個抽象的概念,只能說類屬性和方法,可是,不能給屬性賦具體的值
好比:人類有姓名,可是不能說人類的姓名叫什麼。。。。
對象是一個具體的個例,是將類中的屬性進行具體賦值而來的個體。
好比:張三時人類的一個個體,能夠說張三的姓名叫張三。也就是,張三對人類的每個屬性進行了具體的賦值,那麼張三就是由人類產生的一個對象。
四、使用類和對象的步驟:
① 建立一個類(構造函數):類名必須使用大駝峯法則。即,每一個單詞的首字母都要大寫,spa
function 類名(屬性值1,屬性值2,...){
this.屬性1 = 屬性值1;
this.屬性2 = 屬性值2;
...
this.方法 = fucntion(形參){
//方法中要調用自身屬性必須使用thi.屬性
}
}
② 經過類,實例化(new)出一個對象:code
var obj = new 類名(屬性值);
obj.屬性; //調用屬性
obj.方法(); //調用方法
③ 注意事項:
一、經過類名,new出一個對象的過程,叫作"類的實例化";
二、類中的this,會在實例化的時候指向新new出的對象。
因此,this.屬性、 this.方法 其實是將屬性和方法綁定在即將new出的對象上面;
三、在類中,要調用自身的屬性,必須使用this.屬性。若是,直接使用變量名,則沒法訪問對象的屬性。
四、類名必須使用大駝峯法則,注意與普通函數的分。
五、兩個重要屬性
① constructor :返回當前 對象 的構造函數。
對象
zhangsan.constructor == Person; √
② instanceof :檢測一個對象是否是一個類的實例;blog
lisi instanceof Person √ lisi是經過Person類new出的
lisi instanceof Object √ 全部對象都是Object的實例
Person instanceof Object √ 函數自己也是對象
六、廣義對象與狹義對象:
① 狹義對象:只有屬性和方法,除此以外沒有任何其餘內容;繼承
var obj = {};
var obj = new Object();
② 廣義對象: 用字面量聲明的基本數據類型不是對象,不可以添加屬性和方法
除了用字面量聲明的基本數據類型外JS中萬物皆對象。換句話說,只要可以添加屬性和方法的變量,均可以稱之爲對象。
var s = "12"; //不是對象
s.name = "aaa";
console.log(typeof(s)); //string
console.log(s.name); // undefined 字面量聲明的字符串不是對象,不能添加屬性
var s = new String("123"); //是對象
s.name = "aaa";
console.log(typeof(s)); //object
console.log(s.name); // aaa 使用new關鍵字聲明的字符串是對象,能添加屬性和方法
一、在構造函數中,使用this.屬性聲明,或者在實例化出對象之後,使用"對象.屬性"追加的,都屬於成員屬性或成員方法。也叫實例屬性和實例方法
成員屬性/成員方法: 是屬於由類new出的對象的。
須要使用"對象名.屬性名"調用.
二、經過"類名.屬性名"、"類名.方法名"申明的屬性和方法,稱爲靜態屬性、靜態方法 。也叫類屬性和類方法;
類屬性/類方法,是屬於類的(屬於構造函數)。
經過"類名.屬性名"調用
三、成員屬性是屬於實例化出的對象的,只能使用對象調用;
靜態屬性是屬於構造函數的,只能使用類名調用。
四、在構造函數中使用var申明的變量稱爲私有屬性,使用function申明的函數稱爲私有方法
function Person (){
var num = 1 ; //私有屬性
function func(){} //私有方法
}
私有屬性和私有方法的做用域,只在構造函數中有效。即,只能在構造函數內部使用,在構造函數外部,不管使用對象仍是類名都沒法調用。
function Person(name){
this.name = name; //聲明成員屬性
var sex = "男"; //私有屬性
this.sayTime = function(){ //聲明成員方法
alert("我說當前時間爲"+getTime());
}
this.writTime = function(){
alert("我寫了當前時間爲"+getTime()); //調用私有方法
}
function getTime(){ //私有方法
return new Date;
}
}
/***************************成員屬性/方法*************************/
var zhangsan = new Person("張三"); //類的實例化
zhangsan .age = 18; //追加成員屬性
alert(zhangsan .name); //調用成員屬性
/***************************靜態屬性/方法***************************/
Person.count = "60億"; //聲明靜態屬性
alert(Person.count); //調用靜態屬性
var lisi = new Person("李四");
alert(lisi.count); //undefined 靜態屬性是屬於類的,只能用類名調用
/*************************私有屬性/方法**************/
lisi.sayTime(); //外部間接調用
lisi.writTime();
2 this指向詳解 |
一、相關知識:
對於判斷this的指向問題,總的來講,就是:誰最終調用函數,this就指向誰。
① this指向誰,不該該考慮函數在哪聲明,而應該考慮函數在哪調用;
② this指向的永遠只多是對象,而不多是函數;
③ this指向的對象,叫作函數的上下文(context),也叫函數的調用者。
二、雖然知道了,誰最終調用函數,this就指向誰。可是,仍是以爲有點籠統,不夠詳細。對this的指向問題仍是太模糊。
因而,在這裏,影子特向你們介紹,this指向問題規律的5條通用判斷方法。
① 經過 函數名() 調用的,this永遠指向window;
② 經過 對象.方法 調用的,this指向該對象;
③ 函數做爲 數組 中的一個元素,用數組下標調用的,this指向該數組;
④ 函數做爲Window內置函數的 回調函數 使用,this指向window;
setInterval、 setTimeout
⑤ 函數做爲構造函數,使用 new關鍵字 調用,this指向新new出的對象。
下面,將對每條規律,作出案例,以供你們,理解:
<div id="div1"style="width: 200px;height: 200px;background-color: red;"> 這是一個div </div>
function func(){
console.log(this);
}
var obj ={
func : func
}
function func1(){
func(); //this指向Window
}
//① 經過 函數名() 調用的,this永遠指向window;
func(); //this指向Window
//② 經過 對象.方法 調用的,this指向該對象;
obj.func(); //this指向對象obj
window.onclick = function(){
document.getElementById("div1").onclick = function(){
func(); // 最終仍是使用()調用,全部指向window
}
document.getElementById("div1").onclick = func;//廣義對象,指向div1
}
//③ 函數最爲數組中的一個元素,用數組下標調用的,this指向該數組
var arr = [1,2,3,func,4,5];
arr[3]();
//④ 函數做爲Window內置函數的回調函數使用,this指向window;
setTimeout(func,1000);
//⑤ 函數做爲構造函數,使用new關鍵字調用,this指向新new出的對象。
var obj1 = new func();
下面是一個影子總結的一個綜合案例:
/************************綜合案例****************/
var obj1 = {
name : "obj1",
arr : [func, 1,{name : "obj2",func : func},3,4],
}
obj1.arr[0](); //最終的調用者是數組,this指向數組
setTimeout(obj1.arr[0],1000); //obj1.arr[0僅僅是取到函數func,但並無調用。函數的最終調用者是setTimeout,指向window;這個式子至關於setTimeout(func,1000);
setTimeout(obj1.arr[2].func,1000); //函數的最終調用者是setTimeout.緣由同上↑
obj1.arr[2].func(); //最終的調用者是{name : obj2,func : func},this指向{name : obj2,func : func}
好了,今天影子給你們分享的東西就這麼多了。最後,影子這裏還有一道this指向的題,就一這道題結束今天的分享吧。至於答案就留到下次。哈哈。。。
var fullname = 'John Doe';
var obj = {
fullname: 'Colin Ihrig',
prop: {
fullname: 'Aurelio De Rosa',
getFullname: function() {
return this.fullname;
}
}
};
console.log(obj.prop.getFullname()); //??
var test = obj.prop.getFullname;
console.log(test());
//??
obj.func = obj.prop.getFullname;
console.log(obj.func()); //???
var arr = [obj.prop.getFullname,1,2];
arr.fullname = "JiangHao";
console.log(arr[0]());
console.log(arr[0]); //????