原型
- 原型本身是一個(gè)對(duì)象焰络,這個(gè)對(duì)象的屬性與方法可供其他對(duì)象。
誰有原型
- 默認(rèn)所有的對(duì)象都有原型
誰有prototype
- 默認(rèn)所有的函數(shù)都有prototype
給對(duì)象手動(dòng)添加prototype可以實(shí)現(xiàn)繼承嗎
- 沒什么亂用符喝,因?yàn)閷?duì)象不能配合new關(guān)鍵字創(chuàng)建實(shí)例闪彼。
函數(shù)的特殊性
- 函數(shù)也是對(duì)象的一種,所以也有proto
- 函數(shù)可以用來創(chuàng)建實(shí)例,又有prototype
如何訪問一個(gè)對(duì)象的原型
- 通過proto屬性(但是它是非標(biāo)準(zhǔn)屬性畏腕,不建議開發(fā)中使用)
- 通過constructor屬性得到對(duì)象的構(gòu)造函數(shù)缴川,再訪問其prototype得到原型
prototype的作用
- 用來引導(dǎo)構(gòu)造函數(shù)創(chuàng)建的實(shí)例默認(rèn)原型
proto的作用
- 用來繼承某個(gè)對(duì)象
prototype與proto聯(lián)系
- 通過構(gòu)造函數(shù)創(chuàng)建的實(shí)例,實(shí)例的proto默認(rèn)為構(gòu)造函數(shù)的prototype描馅,除此之外把夸,沒有任何聯(lián)系。
構(gòu)造函數(shù)創(chuàng)建對(duì)象的4個(gè)步驟
- 創(chuàng)建一個(gè)新對(duì)象(本質(zhì)上就是開辟了一塊內(nèi)存空間)
- 設(shè)置新對(duì)象的原型
- 本質(zhì)上就是在這塊內(nèi)存空間中添加了一個(gè)proto屬性
- proto屬性值與構(gòu)造函數(shù)的prototype有關(guān)
- 相當(dāng)于是這樣給proto賦值的:新對(duì)象.proto = 構(gòu)造函數(shù).prototype
- 執(zhí)行構(gòu)造函數(shù)铭污,執(zhí)行時(shí)設(shè)置其this為新實(shí)例
- 返回新實(shí)例的地址
對(duì)象的屬性訪問規(guī)則
優(yōu)先從自身查找恋日,找不到就去原型找,還找不到繼續(xù)去原型的原型找嘹狞,
直到終點(diǎn)岂膳,終點(diǎn)也沒有返回undefined。
對(duì)象的屬性賦值
自己沒有該屬性相當(dāng)于新增磅网,有則修改谈截,并不會(huì)對(duì)其原型上的屬性造成影響。
繼承
- 在js中涧偷,只要一個(gè)對(duì)象能夠使用另一個(gè)對(duì)象的成員簸喂,這種特征就是繼承。
- 在主流的面向?qū)ο笳Z言中燎潮,繼承是類與類之間的關(guān)系喻鳄,在js中繼承是對(duì)象與對(duì)象之間的關(guān)系。
繼承方式
1跟啤、默認(rèn)的原型繼承
function P() {}
P.prototype.fun = function(){};
var p = new P();
2诽表、原型替換
function P() {}
P.prototype = {
constructor: P,
fun: function(){}
};
var p = new P();
3、Object.create
var proObj = {
fun: function(){}
};
var p = Object.create(proObj);
4隅肥、原型組合式
function A() {}
function P() {}
P.prototype = Object.create(A.prototype);
P.prototype = new A();
var p = new P();
屬性復(fù)制
在日常開發(fā)中竿奏,可能會(huì)存在實(shí)現(xiàn)多繼承的需求,上面的原型組合式就可以完成這個(gè)需求腥放。
但是原型組合式如何嵌套過多泛啸,對(duì)于屬性的查找效率是有影響的,而且過長(zhǎng)的原型秃症,也不利于維護(hù)候址。
對(duì)于實(shí)現(xiàn)多繼承,還有另外一種解決方案种柑,這種解決方案有一個(gè)代表岗仑,就是jQuery庫(kù)中提供的extend方法。
實(shí)現(xiàn)屬性復(fù)制函數(shù)封裝
function copy() {
var target = arguments[0];
for(var i = 1, len = arguments.length; i < len; i++) {
for(var key in arguments[i]) {
target[key] = arguments[i][key];
}
}
return target;
}
關(guān)于for in遍歷的補(bǔ)充
- 使用for in的方式遍歷對(duì)象的屬性聚请,是無法遍歷出js內(nèi)置屬性的荠雕。
使用屬性copy的方式給原型添加屬性的優(yōu)點(diǎn)
- 不會(huì)覆寫構(gòu)造函數(shù)默認(rèn)的prototype稳其,那么對(duì)應(yīng)的constructor屬性就不會(huì)丟失
- 可以替代原型組合式的寫法
- 使用靈活簡(jiǎn)單
原型的規(guī)律
- 原型鏈的終點(diǎn)統(tǒng)一是Object.prototype
- 對(duì)象的原型和該對(duì)象的類型有關(guān)
- 比如Person的實(shí)例,原型是Person.prototype
- 比如Animal的實(shí)例炸卑,原型是Animal.prototype
- []的原型鏈結(jié)構(gòu)
- [] ==> Array.prototype ==> Object.prototype ==> null
- {}的原型鏈結(jié)構(gòu)
- {} ==> Object.prototype ==> null
- /abc/的原型鏈結(jié)構(gòu)
- /abc/ ==> RegExp.prototype ==> Object.prototype ==> null
- Person的原型鏈結(jié)構(gòu)
- Person ==> Function.prototype ==> Object.prototype ==> null
- Function的原型鏈結(jié)構(gòu)
- Function ==> Function.prototype ==> Object.prototype ==> null
- Object的原型鏈結(jié)構(gòu)
- Object ==> Function.prototype ==> Object.prototype ==> null
- 構(gòu)造函數(shù)默認(rèn)的prototype既鞠,它統(tǒng)一都繼承Object.prototype
- 比如Person.prototype,原型是Object.prototype
- 比如Animal.prototype盖文,原型是Object.prototype
- 通過這個(gè)規(guī)則嘱蛋,可以自由猜想出任意一個(gè)實(shí)例所有的原型
- 比如Book的實(shí)例,其原型結(jié)構(gòu)為: Book實(shí)例 ==> Book.protoype ==> Object.prototype ==> null
原型鏈
- 一個(gè)對(duì)象五续,所有由proto聯(lián)系在一起的原型洒敏,稱之為這個(gè)對(duì)象的原型鏈。
如何研究一個(gè)對(duì)象的原型鏈結(jié)構(gòu)
- 先通過proto得到對(duì)象的原型
- 然后訪問這個(gè)原型的constructor屬性返帕,確定該原型的身份
- 然后繼續(xù)按照上訴兩個(gè)步驟桐玻,往上研究原型,最終就得到了對(duì)象的原型鏈荆萤。
instanceof -- 運(yùn)算符
- 作用:判斷一個(gè)對(duì)象的原型鏈中是否含有某個(gè)構(gòu)造函數(shù)的prototype
- 語法:對(duì)象 instanceof 構(gòu)造函數(shù)
- 返回值:boolean
hasOwnProperty -- 方法
- 作用:判斷一個(gè)屬性是不是自己的(不包含繼承的屬性)
- 語法:對(duì)象.hasOwnProperty(屬性名)
- 返回值:boolean
in -- 運(yùn)算符
- 作用:判斷能否使用某個(gè)屬性(包含繼承的屬性)
- 語法:屬性名 in 對(duì)象
- 返回值:boolean
delete -- 運(yùn)算符
- 作用:刪除對(duì)象的屬性
- 語法:delete 對(duì)象.屬性名 || delete 對(duì)象[屬性名]
- 返回值:boolean
Function -- 內(nèi)置構(gòu)造函數(shù)
- 作用:創(chuàng)建函數(shù)實(shí)例
- 語法:new Function(形參1镊靴,形參2,...链韭,代碼體)
- 返回值:新創(chuàng)建的函數(shù)實(shí)例
- 特點(diǎn):能夠把字符串當(dāng)做js腳本執(zhí)行
eval -- 內(nèi)置的全局函數(shù)
- 作用:執(zhí)行字符串代碼