JavaScript物件(二)
本篇,主要講了面向物件、this的指向問題,模擬繼承程序
面向物件編程
- 什么面向物件編程?
- 編程,編程就是人們用計算機能懂的語言,告訴計算機自己想做的事情,
- 面向物件的編程的主要思想是把構成問題的各個事物
分解成各個物件,建立物件的目的不是為了完成一個步驟,而是為了描述一個事物在解決問題的程序中經歷的步驟和行為,物件作為程式的基本單位,將程式和資料封裝其中,以提高程式的重用性,靈活性和可擴展性
ps:在學習其它的語言,比如c語言,是面向程序的編程思想,我們現在了解一下,面向物件重點關注的是誰能幫我解決問題,面向程序重點關注的是解決問題的程序,
面向物件的三大特點
- 封裝,
- 把資源整合
- 繼承
- 使用繼承可以用來復用代碼,子類擁有了父類方法,以及重寫
- 多型
- 一種事物的多種形態,分運行時多型(比如方法重寫),編譯時多型(比如方法多載)
創建物件
創建物件,主要可以分為兩類;
- 工廠創建
- 建構式
工廠創建
//舉一個最簡單的工廠創建例子
//需要一個物件,直接工廠創建,呼叫方法就行
var p = createPerson()
function createPerson( name , age ){
var obj = {}
obj.name = name
obj.age = age
return obj
}
ps:工廠創建,就是把創建物件權力交給了他人,自己就只需要把引數告訴工廠就可以了,
建構式
//建構式
function Person( name , age ){
this.name = name
this.age = age
this.say = fuction(){
...
}
}
//實體化一個物件
var p2 = Person()
注意:因為在JavaScript ES5里,就沒有面向物件的寫法,所以我們這上面的面向物件都是通過模擬來是實作的,在es6里,有class關鍵字,在類里寫一個construct來構造,
prototype
我們有沒有發現,在控制臺列印一個function,把函式體展開就能看到一個prototype,這個prototype并不是我們自己定義的一個屬性或者方法,那這個到底是什么呢?
- prototype叫做原型,創建fn函式自動獲得prototype屬性,該屬性是一個物件即該函式的原型物件,我們可以看到原型物件默認會有一個constructor屬性,該屬性是指向函式自身即fn,
原型鏈
我們把_proto_展開,你會在展開后的最下面還能看到一個_proto_,再展開下一個,發現又有,直到你到Object物件的_proto_,不過這得嵌套了多少層了,其實我們可以理解,這樣的_proto_好比是繼承關系,a繼承了b,b就是a的父親,那么a里的_proto_指向的就是b,
應用:
比如你要給陣列寫一個方法,叫做myPop(),洗掉最后一個元素,
當你寫完這個方法后,你可以通過原型方法,給一個陣列物件Array叫上這個方法,Array.prototype.myPop = function(){...}
那么,只要是Array型別的變數,就都可以直接呼叫myPop()方法了
訪問物件
- 用類似陣列方式訪問
var m = new Man('rainbow' , 20 )
訪問name屬性,console.log(m['name']) //rainbow
- for,,,in遍歷每個成員
for ( const key in m ){
console.log( m[key] )
}
洗掉物件
var m = new Man('rainbow' , 20 )
//洗掉指定物件 , 執行成員
delete m1.name
ps:洗掉完后,Man物件就沒有name這個屬性了,
instance of
之前有個typeof,是用來檢查資料型別,
- instance of是用來檢查物件是否為某個物件的實體,回傳true/false
e.g.
var m = new Man('rainbow' , 20 )
m instance of Man //true
m instance of Woman //false
m instance of Object //true,object為任何物件的祖先
hasOwnProperty
- 檢查物件是否有自己的屬性.回傳true/false
var m = {
name : 'rainbwo',
age : 20
}
m.hasOwnProperty('name') //true
m.hasOwnProperty('sex') //flase
in
- 檢查物件中是否有該屬性和方法,回傳true/false
var m = {
name : 'rainbwo',
age : 20
}
'name' in m //true
'age2' in m //false
'toString()' in m //true
ps: 對比hasOwnProperty、in
- hasOwnProperty自定義的,in自定義的+繼承的
- hasOwnProperty只能檢測當前物件中獨有的屬性和方法,in不僅僅是當前的,也能檢測到所有繼承而來的屬性和方法,
this關鍵字
this關鍵字我們不陌生,之前在工廠創建物件時,用到了
this.name = name
this.age = age
-
其實,這個this指的就是當前的物件,使用this可以不用把呼叫者本身全部拼寫出來,并且易于閱讀,
-
但是,實際上,我們的this指向,并沒有那么容易,
比如:
-
在在全域中,console.log(this). 這個this列印的Window,也叫程式背景關系,
-
在一個方法內部(箭頭函式除外),console.log(this),這個this指的就是函式所屬的物件
-
箭頭函式的this指向,Window
-
在事件函式中,this指向事件本身,
-
setTimeout,setInterval的this指向Window
改變this指向的三種方法
Function.prototype.xxx()
- call()
- apply()
- bind()
//定義test函式
function test(attr1,attr2,attr3) {
this.attr1 = attr1
this.attr2 = attr2
this.attr3 = attr3
}
//實體化一個物件
var obj = new Object(a , b, c);
-
test.call( obj , 1 , 2 , 3 )
call直接把this指向了obj
-
test.apply( obj ,[1 , 2 , 3])
apply指向了obj,并且用一個陣列來傳引數
-
test.bind( obj ).(1 , 2 , 3)
test.bind()把this指向了obj,并且回傳了一個新的物件
ps:在JavaScript的語法里,就只有這三種方法可以改變this的指向
繼承
繼承就是讓子類擁有父類的屬性和方法
在es5里,沒有繼承的語法 ,es6有
所以我們可以來模擬一下
//父類
function Person(name , age ) {
this.name = name
this.age = age
}
//子類
Man 、 Woman
function Man( name , age , job ){
//建構式的偽裝,也就是通過this,改變指向
Person.call(this , name , age )//等價于,呼叫了Persion()
this.job = job
}
ps:
- 建構式的偽裝,其實就是繼承了父類的屬性和方法,用this指向的改變,推薦使用call()
- 但是,這樣還不夠,這里繼承不完全,當我們使用instance of 檢測,會找不到繼承的屬性以及方法,因此還需要最關鍵的一步
Man.prototype = Person.prototype
上面這一步叫做,原型繼承,這樣才算是真正的繼承了,
謝謝大家閱讀,鄙人知識、能力不足,如果講的不好或者不正確的地方,還請原諒,支持原創
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/251593.html
標籤:其他
上一篇:溫習資料演算法—貪吃蛇
下一篇:js模仿京東首頁的倒計時功能
