說完閉包,我想原型和原型鏈是js中的難點也是重點,明白了原型和原型鏈會讓我們在後面不管是學習還是工作都會更加高效,並且原型和原型鏈會是面試中必不可少的話題
任何物件都有乙個原型物件,這個原型物件由物件的內建屬性_proto_指向它的建構函式的prototype指向的物件,即任何物件都是由乙個建構函式建立的,但是不是每乙個物件都有prototype,只有方法才有prototype。其實很簡單,就幹了三件事情:
1
var obj =
;2 obj.__proto__ = base.prototype;
3 base.
call
(obj)
;
第一行,我們建立了乙個空物件obj
第二行,我們將這個空物件的__proto__成員指向了base函式物件prototype成員物件
第三行,我們將base函式物件的this指標替換成obj,然後再呼叫base函式,於是我們就給obj物件賦值了乙個id成員變數,這個成員變數的值是」base」,關於call函式的用法。
在談原型鏈之前,我們首先要了解自定義函式與 function 之間是什麼關係,而建構函式、原型和例項之間又存在什麼千絲萬縷的關係呢?
其實,所有的函式都是 function 的例項。在建構函式上都有乙個原型屬性 prototype,該屬性也是乙個物件;那麼在原型物件上有乙個constructor 屬性,該屬性指向的就是建構函式;而例項物件上有乙個 proto 屬性,該屬性也指向原型物件,並且該屬性不是標準屬性,不可以用在程式設計中,該屬性用於瀏覽器內部使用。
// _proto_
在函式裡有乙個屬性prototype
由該函式建立的物件缺省會連線到該屬性上
//prototype 與 _proto_ 的關係
_proto_是站在物件角度來說的
function
person()
var p =
newperson()
;//方法才有prototype,普通物件沒有prototype
console.
log(person.prototype)
;// object{}
console.
log(p.prototype)
;// undifined
//任何物件都是有建構函式的,person這種方法的建構函式是function。
//constructor很容易被改變,一般不用它,此處列印的是下列物件的建構函式是什麼。
console.
log(p.constructor)
;//function person(){}
console.
log(person.constructor)
;//function function(){}
console.
log(
.constructor)
;// function object(){}
console.
log(object.constructor)
;// function function() {}
console.
log(
.constructor)
;//function array(){}
用function宣告的都是函式,而如果直接呼叫的話,那麼person()就是乙個普通函式,只有用函式new產生物件時,這個函式才是new出來物件的建構函式。
//建立建構函式
function word
(words)
word.prototype =
}//建立例項
var w =
newword
("hello world");
w.print
=function()
w.print()
;//hello world
w.alert()
;//hello world
print()方法是w例項本身具有的方法,所以w.print()列印hello world;alert()不屬於w例項的方法,屬於建構函式的方法,w.alert()也會列印hello world,因為例項繼承建構函式的方法。
例項w的隱式原型指向它建構函式的顯式原型,指向的意思是恆等於
w.__proto__ ==
= word.prototype
當呼叫某種方法或查詢某種屬性時,首先會在自身呼叫和查詢,如果自身並沒有該屬性或方法,則會去它的__proto__屬性中呼叫查詢,也就是它建構函式的prototype中呼叫查詢。所以很好理解例項繼承建構函式的方法和屬性:
w本身沒有alert()方法,所以會去word()的顯式原型中呼叫alert(),即例項繼承建構函式的方法。
原型鏈的核心就是依賴物件的_proto_的指向,當自身不存在的屬性時,就一層層的扒出建立物件的建構函式,直至到object時,就沒有_proto_指向了。
因為_proto_實質找的是prototype,所以我們只要找這個鏈條上的建構函式的prototype。其中object.prototype是沒有_proto_屬性的,它==null。最簡單的原型鏈分析
function
person
(name)
var p =
newperson()
;//p ---> person.prototype --->object.prototype---->null
屬性搜尋原則:
當訪問乙個物件的成員的時候,會現在自身找有沒有,如果找到直接使用。
如果沒有找到,則去 原型鏈指向的物件的建構函式的prototype中找,找到直接使用,沒找到就返回undifined或報錯。
//原型繼承的基本案例
function
person
(name, age)
//1.直接替換原型物件
var parent =
}person.prototype = parent;
var p =
newperson
("張三",50
);p.sayhello()
;//2.混入式原型繼承
console.
log(
"混入式原型繼承");
function
student
(name, age)
var parent2 =
}for
(var k in parent2)
var p =
newstudent
("張三",50
);p.sayhello()
;
查詢屬性,如果本身沒有,則會去__proto__中查詢,也就是建構函式的顯式原型中查詢,如果建構函式中也沒有該屬性,因為建構函式也是物件,也有__proto__,那麼會去它的顯式原型中查詢,一直到null,如果沒有則返回undefined
p.proto.constructor == function person(){}
p._proto.proto== object.prototype
p._proto.proto.proto== object.prototype.proto== null
通過__proto__形成原型鏈而非protrotype
JS原型和原型鏈
建立建構函式 function word words word.prototype 建立例項 var w new word hello world w.print function w.print hello world w.alert hello world function.prototype....
js原型鏈和原型
1 原型 在js中一切皆物件,那原型也是乙個物件,通過原型可以實現物件的屬性繼承,js的物件中包含著乙個 prototype 內部屬性,這個屬性所對應的就是物件的原型。prototype 作為物件的內部屬性不能被直接訪問,所以為了方便檢視乙個物件的原型,提供了 proto 這個非標準的訪問器,在js...
JS 原型和原型鏈
先宣告乙個建構函式 function people name,age 把類的方法寫在建構函式原型物件中,子類就不能再通過呼叫父類建構函式來繼承方法 屬性還是可以繼承 給people的原型新增方法 people.prototype.speak function 建立子類繼承people functio...