什麼是原型和原型鏈
1、原型分為顯式原型和隱式原型。顯示原型對應的是prototype屬性,隱式原型對應的是__proto__屬性。
2、所有物件(萬物皆物件)都有__proto__屬性,包括函式、示例等,只有函式才有prototype屬性。
3、prototype屬性值其實也是乙個物件,型別為object。它有乙個自帶屬性constructor,這個constructor是乙個指標,指向函式本身。比如 function animal(){}。 animal是乙個函式指標,可以叫函式物件。animal.prototype是乙個object物件。animal.prototype.constructor == animal。
4、一般情況下,乙個例項的__proto__屬性等於例項的型別的原型。這句話比較抽象。舉個例子,var animal = new animal(),這裡 animal.proto= animal.prototype。通俗的說法可以為,animal的原型為animal.prototype,但是這裡其實涉及到顯式和隱式原型的概念,很容易用混。
5、如果訪問乙個物件的屬性,其查詢順序是,先查詢物件本身的屬性(可以理解為給this新增的屬性),然後查詢例項的__proto__(即原型)中的屬性,在然後查詢原型的__proto__裡的屬性,就這這樣一直查詢下去,直到找到。最終找到的是object.prototype.proto,它等於 null。 其實這個過程就是原型鏈。通俗點就是以__proto__屬性為媒介,把物件相關的原型以鏈式方式串聯起來,以方便屬性和方法的訪問。prototype就是要串的原型。可以把__proto__理解為線,而prototype是珠子。
6、constructor屬性指向原型的構造方法。其實這個屬性在示例new的過程中是沒有作用的。在例項的instance of 方法也不是以它為依據的。後來我想到這個屬性有乙個作用。比如,我們有乙個例項,但是無法獲取到例項的類(匿名自執行函式),可以通過例項的constructor獲取到這個類,然後給類新增方法或屬性。不過這種使用方法好像也沒有什麼必要。只是為了加深理解。
//constructor的作用,匿名自執行函式場景。
var bydcar,ytcar ;
(function ()
bydcar =
newcar()
; ytcar=
newcar()
;})(
);bydcar.constructor.prototype.name =
'byd'
; console.
log(
"bydcar車的品牌:"
+ bydcar.name)
; console.
log(
"ytcar車的品牌:"
+ bydcar.name)
;
7、new方法都做了哪些事情。這個還是以var animal = new animal();為例。
首先是 建立乙個空物件。
然後把物件的__proto__屬性指向原型。
接下來,設定函式的this指向上邊的物件,並執行函式。
//new的過程。
var obj =
; obj.__proto__ = animal.prototype;
animal.
call
(obj)
;//如果animal中有return 就是把return結果作為new的物件,否則就是上邊建立的obj物件
原型鏈和原型有什麼用,哪些場景用
理解了上邊的內容之後,你有沒有感覺原型鏈的方式很像面相物件程式設計裡邊用到得繼承的思想呢。下面就是把我用原型鏈實現的繼承示例。使用面相物件的思想編寫js**,會使得**的復用性更好,抽象程度更深,邏輯也更清晰。
/**原型鏈繼承,修改子類的原型為父類的例項,那麼cat.__proto__ == cat.prototype == animal,原型鏈查詢
* 就是cat----->cat.__proto__-------->animal------>animal__proto__---->animal.prototype--->animal.prototype.__proto__------>object.prototype----->object.prototype.__proto__------->null*/
function animal
(name)
this
.getname = function (
)this
.setname = function (newname)}
animal.prototype.eat = function (
)/*var animal = new animal('小羊');
animal.__proto__
animal.eat();
animal.sleep();*/
//原型鏈繼承
//缺點1、無法實現多繼承。2、所有例項共享同乙個父例項。 3、建立子類時無法給父類傳遞引數。
function cat
(catname)
cat.prototype =
newanimal
('動物');
var cat =
newcat
('小貓');
var cat1 =
newcat
('小貓1');
cat.
setname
('1111');
var aaa = cat.
getname()
;//構造繼承 1、解決建立時無法給子類傳遞引數的問題。2、解決多繼承問題。
//缺點:1、例項並不是父例項 2、不能繼承父親的原型方法。3、每個子類中都有父類函式的副本。
function dog
(dogname)
var dog =
newdog
("小狗");
dog.
sleep()
;沒有此方法。
//例項繼承 此種方式個人覺得沒有任何意思,new出來的直接是父例項。只不過在構造方法中可以定義一些屬性和方法。
function cow
(cowname)
return cow;}
var cow =
newcow
('牛');
if(cow instanceof animal)
cow.cowname;
//拷貝繼承 1支援多繼承 2 效率低
function fish
(name)}
var fish =
newfish
("魚");
fish.
eat();
fish.name;
//組合繼承 推薦,僅僅是呼叫了兩次父類的構造方法而已。
function tiger
(name)
tiger.prototype =
newanimal()
; = tiger;
tiger.prototype.tigername =
"老虎";
var tiger =
newtiger()
;if(tiger instanceof animal)
if(tiger instanceof tiger)
//寄生組合繼承
function shark
(name)
(function ()
super.prototype = animal.prototype;
shark.prototype =
newsuper()
;})(
);var shark =
newshark
("鯊魚");
shark.prototype.constructor = shark;
shark.prototype.bite = function ()if
(shark instanceof shark)
if(shark instanceof animal)
var aaa =
typeof
(shark);
debugger;
shark.
bite()
;
原型與原型鏈
原型有兩種 1為顯示原型,2為隱式原型 1.顯示原型 a prototype b 每個函式都有乙個顯示原型prototype當然函式也有隱式原型 c 原型就是函式的乙個屬性,這個屬性名叫做prototype d 這個屬性即prototype的型別是object 2.隱式原型 a proto b 每個...
原型與原型鏈
圖中一共標了7條線,就一條一條的講,講完了就應該懂了 已知 1.函式是物件,原型也是物件 2.proto 每乙個物件都有,prototype是函式特有的 3.物件的 proto 屬性指向該物件建構函式的 原型 prototype 線1.物件f1的 proto 屬性指向其建構函式的原型 其建構函式 f...
原型與原型鏈
值型別 string,number,boolean,undefined function person var p1 newperson p1即為建構函式person 的例項化物件 var arr 10 20,30 40,50 60 這種語法糖形式的物件建立,是由array 函式建立簡化而來的。這個...