原型對(duì)象:
1(prototype存在于構(gòu)造函數(shù)中,其實(shí)任意函數(shù)都有,我們不關(guān)注而已)函數(shù)都有protoType屬性,這個(gè)屬性是一個(gè)指針, 指向 即原型對(duì)象。?
2? js是一種基于原型的語言,每個(gè)對(duì)象擁有一個(gè)原型對(duì)象,對(duì)象以其原型為模板,從原型繼承方法和屬性。原型對(duì)象也可能有原型,以此類推,原型鏈。
注意: 原型鏈中的方法和屬性沒有被復(fù)制到其他對(duì)象,它們被訪問需要通過原形鏈。
注意:沒有官方的方法直接訪問原形對(duì)象。
注意:prototype屬性,繼承成員被定義的地方。繼承的屬性和方法是定義在prototype屬性上的,prototype屬性的值是一個(gè)對(duì)象,我們希望被原型鏈下游的對(duì)象繼承的屬性和方法,都存儲(chǔ)其中。
原型鏈:當(dāng)對(duì)象使用屬性的時(shí)候,現(xiàn)在自身進(jìn)行查找,有就直接使用,沒有就沿著__proto__這條鏈繼續(xù)往下查找,直到找到Object原型位置,有就返回相應(yīng)的值,沒有就返回underfined.
實(shí)現(xiàn)繼承:
函數(shù)的原型對(duì)象constructor默認(rèn)指向函數(shù)本身,原型對(duì)象除了有原型屬性外,為了實(shí)現(xiàn)繼承,還有一個(gè)原型鏈指針_proto_,該指針指向上一層的原型對(duì)象,而上一層的原型對(duì)象的結(jié)構(gòu)依然類似,這樣利用_proto_一直指向Object的原型對(duì)象上,而Object的原型對(duì)象用Object._proto_ = null表示原型鏈的最頂端,如此變形成了javascript的原型鏈繼承。
原型對(duì)象中有兩個(gè)默認(rèn)的不可枚舉屬性:constructor和 __ proto__ ;constructor指向?qū)ο螅?__ proto__為隱式原型屬性
原型分為兩種,顯式原型prototype和隱式原型__ proto__
function?F()?{}?//?F?是一個(gè)函數(shù),函數(shù)也是對(duì)象,而且每個(gè)函數(shù)都有一個(gè)屬性叫:"prototype"
var?o?=?new?F();?//?F.prototype?就是?o?的原型對(duì)象
console.log(o.name);
//?輸出:?undefined
F.prototype.name?=?"foo";
console.log(o.name);
//?輸出:?foo
//?上面這個(gè)例子是想說明:通過?new?在對(duì)象?o?與對(duì)象?F.prototype?之間建立了聯(lián)系,?這個(gè)建立聯(lián)系
//?的方式有人叫?"原型繼承"?。?當(dāng)訪問的對(duì)象屬性不存在時(shí),就會(huì)沿著原型鏈去查找。
JS(原型和原型鏈)
題目1.如何準(zhǔn)確判斷一個(gè)變量是數(shù)組類型
need-to-insert-img
使用 instanceof 方法
題目2.寫一個(gè)原型鏈繼承的例子
need-to-insert-img
實(shí)例:封裝 DOM 查詢
定義構(gòu)造函數(shù) Elem,屬性封裝成 id?
need-to-insert-img
打印出所有的 html
need-to-insert-img
將所有的 html 變?yōu)?hello imooc ,并且點(diǎn)擊彈出 ‘clicked’
need-to-insert-img
鏈?zhǔn)讲僮?/p>
need-to-insert-img
題目3.描述 new 一個(gè)對(duì)象的過程
need-to-insert-img
1.創(chuàng)建一個(gè)新對(duì)象
2.this 指向這個(gè)新對(duì)象
3.執(zhí)行代碼,即對(duì) this 賦值
4.返回 this
一、構(gòu)造函數(shù)
need-to-insert-img
大寫字母開頭一般都是構(gòu)造函數(shù)
new 的過程:
1.var f = new Foo('zhangsan',20)? 將參數(shù)傳進(jìn)去,函數(shù)中的 this 會(huì)變成空對(duì)象
2.this.name = name;this.age = age;this.class = 'class-1' 為賦值;return this 為實(shí)際的運(yùn)行機(jī)制
3.return 之后賦值給 f ,f 具備了 f.name = zhangsan、f.age = 20、f.class = 'class-1'
4.繼續(xù)執(zhí)行到 f1 ,則 f1.name = lisi、f1.age = 22、f1.class = 'class-1'
二、構(gòu)造函數(shù)(擴(kuò)展)
1.var a = {} 其實(shí)是 var a = new Object()的語法糖??(a 的構(gòu)造函數(shù)是 Object 函數(shù))
2.var a = [] 其實(shí)是 var a = new Array()的語法糖? ??(a 的構(gòu)造函數(shù)是 Array 函數(shù))
3.function Foo(){...}其實(shí)是 var Foo = new Function(...)? ? ?(Foo 的構(gòu)造函數(shù)是 Function 函數(shù))
4.使用 instanceof 判斷一個(gè)函數(shù)是否是一個(gè)變量的構(gòu)造函數(shù)? ?(判斷一個(gè)變量是否為“數(shù)組”? 變量 instanceof Array)
三、原型規(guī)則
1.所有的引用類型(數(shù)組、對(duì)象、函數(shù))都具有對(duì)象特性,即可自由擴(kuò)展屬性(除了“null”)
need-to-insert-img
2.所有的引用類型(數(shù)組、對(duì)象、函數(shù))都有一個(gè) _proto_ 屬性(隱式原型屬性),屬性值是一個(gè)普通的對(duì)象
need-to-insert-img
3.所有的函數(shù),都有一個(gè) prototype(顯式原型)屬性,屬性值也是一個(gè)普通的對(duì)象
need-to-insert-img
4.?所有的引用類型(數(shù)組、對(duì)象、函數(shù)), _proto_ 屬性值(隱式原型屬性)指向它的構(gòu)造函數(shù)的“prototype”屬性值
need-to-insert-img
?當(dāng)試圖得到一個(gè)對(duì)象的某個(gè)屬性時(shí),如果這個(gè)對(duì)象本身沒有這個(gè)屬性,那么會(huì)去它的_proto_(即它的構(gòu)造函數(shù)的 prototype(顯式原型))中尋找
5.
need-to-insert-img
f.printName() 中 f 的(自身)屬性是 name ,屬性值是 zhangsan
f.alertName() 中 f 的隱式原型正好指向 Foo 的顯式原型 Foo.prototype, f 本身沒有 alertName 的屬性,會(huì)去其隱式原型中尋找,故執(zhí)行f.alertName()時(shí)會(huì)執(zhí)行Foo.prototype.alertName = function (),因?yàn)?Foo 擴(kuò)展 function,故輸出 zhangsan
故通過對(duì)象的屬性的形式來執(zhí)行函數(shù)的時(shí)候,無論函數(shù)是自身的屬性還是從原型中得到的屬性, this 永遠(yuǎn)指向 f 自身,沒有指向函數(shù),故執(zhí)行f.alertName()時(shí),alert(this.name) 中的 this 就是 f 。
6.循環(huán)對(duì)象自身的屬性
need-to-insert-img
if (f.hasOwnProperty(item)) 中遍歷 f 時(shí),判斷遍歷中的 item,是否可以通過 hasOwnProperty 驗(yàn)證,通過則表明它是 f 自身的屬性,未通過則表明 是 f 通過原型獲得的屬性
四、原型鏈
need-to-insert-img
f.toString(),當(dāng)這個(gè)對(duì)象沒有這個(gè)屬性的時(shí)候,去它自身的隱式原型中找,它自身的隱式原型就是它構(gòu)造函數(shù)(Foo)的顯式原型(Foo.prototype)但顯式原型(Foo.prototype)中并沒有 toString ;但顯式原型(Foo.prototype)也是對(duì)象,也要在它的隱式原型中找,即在其構(gòu)造函數(shù)?(Object?)的顯式原型中去找 toString.?故要在 f._proto_(隱式原型)的._proto_(隱式原型)中找,如圖所示,故輸出 null
need-to-insert-img
方框?yàn)?構(gòu)造函數(shù),圓框?yàn)?對(duì)象,特例:Object.prototype 的 隱式原型是 null (JS避免死循環(huán))
?五、instanceof
?判斷?引用類型?屬于哪個(gè)?構(gòu)造函數(shù)?的方法
need-to-insert-img
f instanceof FOO 的判斷邏輯:f 是 Foo new出來的一個(gè)類型(正確)
判斷方式:f 的隱式原型(proto)一層一層往上,能否對(duì)應(yīng)到 Foo.prototype(顯式原型)
?試判斷:f instance of Object? (正確)見上圖