——————————
JavaScript語法結構
「物件【重】」
——————————
物件【面向物件】
== 萬事萬物皆為物件 ==
為什么要用物件
在記錄一個資料值時,基本上都是使用變數,保存多個資料值時,可以使用陣列,
對于記錄資料而言,可以使用陣列記錄大量資料,但是陣列中的資料只能通過索引值進行訪問,并不明確每個資料的實際價值,而在開發中基本上每一步都需要明確每個資料的實際價值是什么,而且資料量變得非常龐大時索引也很混亂,
為了解決這種問題,使用物件的方式去解決,在物件中使用屬性進行記錄資料,可以通過屬性名稱明確資料的價值
面向物件
面向物件是一個思想
面向物件是把事務分解成為一個個物件,然后由物件之間分工與合作,
面向物件的三大特征
封裝、繼承、多型性
面向程序與面向物件對比
| 面向程序 | 面向物件 | |
|---|---|---|
| 優點 | 性能比面向物件高,適合跟硬體聯系很緊密的東西,例如單片機就采用的面向程序編程, | 易維護、易復用、易擴展,由于面向物件有封裝、繼承、多型性的特性,可以設計出低耦合的系統,使系統 更加靈活、更加易于維護 |
| 缺點 | 不易維護、不易復用、不易擴展 | 性能比面向程序低 |
通過字面量創建物件
就是使用創建變數的方式,等號后面給一對花括號,花括號里面包含了表達這個具體事務(物件)的屬性和方法,花括號里面的內容以“鍵值對”形式表示
鍵:關鍵詞,在一個物件內是唯一的(包含:屬性名、方法名)
值:資料值,可以重復完全取決于實際要求,而且資料型別不限
物件的使用
-
物件的屬性
物件中存盤的具體資料,屬性名是鍵值對中的鍵,而存盤的具體資料是鍵所對應的值
-
物件的方法
物件中存盤的具體函式,方法名是鍵值對中的鍵,而具體的函式是鍵所對應的匿名函式
-
訪問物件成員
- 訪問物件里面的屬性,通過“物件名稱.屬性名”方式進行訪問
- 訪問物件里面的屬性還有一種方式,通過“物件名稱[“屬性名”]”方式進行訪問,和陣列索引訪問元素方式類似,區別在于訪問屬性方括號中使用的是鍵名稱,必須是字串
- 訪問物件里面的方法,通過“物件名稱.方法名()”方式進行訪問
總結:變數、屬性及函式、方法
- 屬性是物件的一個組成部分,而變數不是物件的組成成員,而且變數只是一個存盤資料的容器,基本上沒有任何的實際含義,
- 方法是物件的一個組成部分,而函式不是物件的組成成員,函式只是單獨的封裝了一些操作演算法的簡單容器,
通過new Object創建
var man=new Object();
Object:是復雜資料型別object的原始物件(原名稱)
new:創建一個新的這個型別成員
通過new Object();會創建出來一個新的object型別的資料,而且這個資料裝在man變數里面,object型別就是js代碼中的所有資料型別的一個基型別,只要是我們接觸的型別都是由object型別所演變而來
屬性方法的添加
通過之前學習的呼叫的方式進行添加
var man=new Object();
man.name="張三";
man.age=20;
man.say=function(){
return "hello";
}
console.log(man.name);
console.log(man.say());
通過建構式創建
構造方法:是一種特殊的函式,主要是用來初始化物件,也是物件的一個成員,這個成員方法特殊到呼叫方式為隱式呼叫,這個函式的執行在創建物件的時候默認執行,
其實通過new Object();這種方式創建物件時其實也使用的是呼叫建構式的方式進行創建的物件
建構式執行的價值
- 建構式的執行必須使用new關鍵字搭配使用
- 建構式執行完創建了一個建構式所屬的原始物件
- 可以通過建構式對原始物件中的屬性等進行初始化賦值
建構式的使用
// 創建建構式和創建函式基本上一樣
function Man(引數1,引數2,...){
this.name=引數1;
this.age=引數2;
......
}
function Man(){
this.name="張三";
this.age=20;
this.say=function(){
console.log("你好");
}
}
var man1=new Man();
console.log(man1.name);
man1.say();
- 建構式和普通函式沒有什么區別
- 建構式的函式名使用帕斯卡命名法
- 建構式內的屬性和方法創建必須使用"this.名稱"方式進行創建添加
- 建構式中不需要return回傳結果
- 當創建物件的時候(建構式的呼叫),必須使用new 來呼叫建構式
- 使用建構式的方式創建物件,可以稱之為創建了一個類,而建構式對這一類物件的公共部分進行了抽象處理,類和物件的概念:類是物件的抽象化概念,而物件是類的一種具體表現,
- 創建物件使用的new 物件名();特質某一類,通過new關鍵字創建屬于這一類的一個新成員物件,這個程序類的實體化物件成員
new關鍵字
- 在建構式代碼開始執行之前,創建一個新物件
- 修改this的指向,把this指向實體化后的新物件
- 執行函式的代碼
- 在函式完成之后,回傳this,(可以通過物件中的某個函式創建這個物件自己)
遍歷語法
通過遍歷獲取物件成員
function Man(){
this.name="張三";
this.age=20;
this.say=function(){
console.log("你好");
};
this.self=function(){
return this;
}
}
var man1=new Man();
for (var item in man1) {
console.log(item);
}
使用遍歷語法對物件進行遍歷,遍歷到的每一個元素是物件“鍵值對”中的鍵的值,如果使用這種遍歷方式進行遍歷陣列,那么得到的結果是每個元素的索引
建構式和原型
靜態成員和實體成員
實體成員
實體成員就是建構式內部通過this添加的成員,實體成員只能通過實體化的物件來訪問
靜態成員
靜態成員在建構式本身上添加的成員,靜態成員只能通過建構式(類名)來訪問
建構式的問題
建構式方法很好用,但是存在浪費記憶體的問題,一個物件的初始化主要就是憑借建構式實作的,建構式除了初始化物件資料之外,回傳一個物件實體,
如果同一個函式能夠作用到任何物件,這樣就會節省很多記憶體
建構式原型prototype
建構式通過原型分配的函式是所有物件所共享的,
JavaScript 規定,每一個建構式都有一個prototype 屬性,指向另一個物件,注意這個prototype就是一個物件,這個物件的所有屬性和方法,都會被建構式所擁有,
我們可以把那些不變的方法,直接定義在 prototype 物件上,這樣所有物件的實體就可以共享這些方法,
物件原型
物件都會有一個屬性 _proto_ 指向建構式的 prototype 原型物件,之所以我們物件可以使用建構式 prototype 原型物件的屬性和方法,就是因為物件有 __proto__ 原型的存在,
__proto__物件原型和原型物件 prototype 是等價的
__proto__物件原型的意義就在于為物件的查找機制提供一個方向,或者說一條路線,但是它是一個非標準屬性,因此實際開發中,不可以使用這個屬性,它只是內部指向原型物件 prototype

constructor建構式
物件原型( _proto_)和建構式(prototype)原型物件里面都有一個屬性 constructor 屬性 ,constructor 我們稱為建構式,因為它指回建構式本身,
constructor 主要用于記錄該物件參考于哪個建構式,它可以讓原型物件重新指向原來的建構式,
一般情況下,物件的方法都在建構式的原型物件中設定,如果有多個物件的方法,我們可以給原型物件采取物件形式賦值,但是這樣就會覆寫建構式原型物件原來的內容,這樣修改后的原型物件 constructor 就不再指向當前建構式了,此時,我們可以在修改后的原型物件中,添加一個 constructor 指向原來的建構式,
如果我們修改了原來的原型物件,給原型物件賦值的是一個物件,則必須手動的利用constructor指回原來的建構式
原型鏈
每一個實體物件又有一個__proto__屬性,指向的建構式的原型物件,建構式的原型物件也是一個物件,也有__proto__屬性,這樣一層一層往上找就形成了原型鏈,

建構式、實體和原型物件三角關系
1.建構式的prototype屬性指向了建構式原型物件
2.實體物件是由建構式創建的,實體物件的__proto__屬性指向了建構式的原型物件
3.建構式的原型物件的constructor屬性指向了建構式,實體物件的原型的constructor屬性也指向了建構式
原型鏈和成員的查找機制
任何物件都有原型物件,也就是prototype屬性,任何原型物件也是一個物件,該物件就有__proto__屬性,這樣一層一層往上找,就形成了一條鏈,我們稱此為原型鏈;
- 當訪問一個物件的屬性(包括方法)時,首先查找這個物件自身有沒有該屬性,
- 如果沒有就查找它的原型(也就是 __proto__指向的 prototype 原型物件),
- 如果還沒有就查找原型物件的原型(Object的原型物件),
- 依此類推一直找到 Object 為止(null),
- __proto__物件原型的意義就在于為物件成員查找機制提供一個方向,或者說一條路線,
原型物件中this指向
建構式中的this和原型物件的this,都指向我們new出來的實體物件
通過原型為陣列擴展內置方法
繼承
call()
- call()可以呼叫函式
- call()可以修改this的指向,使用call()的時候 引數一是修改后的this指向,引數2,引數3…使用逗號隔開連接
子建構式繼承父建構式中的屬性
- 先定義一個父建構式
- 再定義一個子建構式
- 子建構式繼承父建構式的屬性(使用call方法)
借用原型物件繼承方法
- 先定義一個父建構式
- 再定義一個子建構式
- 子建構式繼承父建構式的屬性(使用call方法)
ES5新增方法
陣列方法forEach遍歷陣列
陣列方法filter過濾陣列
陣列方法some
some和forEach區別
- 如果查詢陣列中唯一的元素, 用some方法更合適,在some 里面 遇到 return true 就是終止遍歷 迭代效率更高
- 在forEach 里面 return 不會終止迭代
trim方法去除字串兩端的空格
獲取物件的屬性名
Object.keys(物件) 獲取到當前物件中的屬性名 ,回傳值是一個陣列
Object.defineProperty
Object.defineProperty設定或修改物件中的屬性
Object.defineProperty(物件,修改或新增的屬性名,{
value:修改或新增的屬性的值,
writable:true/false,//如果值為false 不允許修改這個屬性值
enumerable: false,//enumerable 如果值為false 則不允許遍歷
configurable: false //configurable 如果為false 則不允許洗掉這個屬性 屬性是否可以被洗掉或是否可以再次修改特性
})
this
函式內部的this指向
這些 this 的指向,是當我們呼叫函式的時候確定的,呼叫方式的不同決定了this 的指向不同,一般指向我們的呼叫者.

改變函式內部 this 指向
call方法
call()方法呼叫一個物件,簡單理解為呼叫函式的方式,但是它可以改變函式的 this 指向
應用場景: 經常做繼承.
apply方法
apply() 方法呼叫一個函式,簡單理解為呼叫函式的方式,但是它可以改變函式的 this 指向,
應用場景: 經常跟陣列有關系
bind方法
bind() 方法不會呼叫函式,但是能改變函式內部this 指向,回傳的是原函式改變this之后產生的新函式,如果只是想改變 this 指向,并且不想呼叫這個函式的時候,可以使用bind
應用場景:不呼叫函式,但是還想改變this指向
call、apply、bind三者的異同
-
共同點 : 都可以改變this指向
-
不同點:
- call 和 apply 會呼叫函式, 并且改變函式內部this指向.
- call 和 apply傳遞的引數不一樣,call傳遞引數使用逗號隔開,apply使用陣列傳遞
- bind 不會呼叫函式, 可以改變函式內部this指向.
-
應用場景
- call 經常做繼承.
- apply經常跟陣列有關系. 比如借助于數學物件實作陣列最大值最小值
- bind 不呼叫函式,但是還想改變this指向. 比如改變定時器內部的this指向.
高階函式
高階函式是對其他函式進行操作的函式,它接收函式作為引數或將函式作為回傳值輸出,

此時fn 就是一個高階函式
函式也是一種資料型別,同樣可以作為引數,傳遞給另外一個引數使用,最典型的就是作為回呼函式,
同理函式也可以作為回傳值傳遞回來
閉包
變數的作用域復習
變數根據作用域的不同分為兩種:全域變數和區域變數,
- 函式內部可以使用全域變數,
- 函式外部不可以使用區域變數,
- 當函式執行完畢,本作用域內的區域變數會銷毀,
什么是閉包
閉包(closure)指有權訪問另一個函式作用域中變數的函式,簡單理解就是 ,一個作用域可以訪問另外一個函式內部的區域變數,

閉包的作用
作用:延伸變數的作用范圍,
END~~
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/265935.html
標籤:其他
上一篇:網頁字體更清晰的css用什么?
