摘要:構(gòu)造函數(shù),實(shí)例對象和原型對象的關(guān)系實(shí)例對象就是通過構(gòu)造函數(shù)創(chuàng)造的,默認(rèn)擁有一個屬性指向其構(gòu)造函數(shù)。
什么是原型
首先,原型是一個對象。而且所有的對象都有一個原型(有一種例外:當(dāng)把對象的原型設(shè)為null時(shí)),并且任何對象都可以成為一個原型。
當(dāng)我們定義一個對象時(shí) var a = new Object(); 默認(rèn)的原型在原型鏈的頂端。
原型有什么好處原型最大的好處體現(xiàn)在它的 共享 的特性。所有原型對象的實(shí)例對象共享它所包含的屬性和方法。所以我們常用利用原型來創(chuàng)建對象,也就是 原型模式。
原型模式原型模式 是一種用來創(chuàng)建多個實(shí)例對象的方法,我們常常把它和 構(gòu)造函數(shù)結(jié)合起來用來創(chuàng)建特定類型的對象。
我們創(chuàng)建的每一個函數(shù)都有一個 prototype 屬性,這個屬性是一個指針,指向一個對象。這個對象的用途是包含可以由特定類型的所有實(shí)例共享的屬性和方法。這個對象就是實(shí)際上通過調(diào)用構(gòu)造函數(shù)而創(chuàng)建的 實(shí)例對象 的原型對象。看代碼:
// 構(gòu)造函數(shù) function Person(){}; Person.prototype.name = "darko"; Person.prototype.age = 21; Person.prototype.sayName = function(){ alert(this.name); } var person1 = new Person(); person1.sayName(); // "darko" var person2 = new Person(); person2.sayName(); // "darko"
我們將所有的屬性和sayName()方法添加到了構(gòu)造函數(shù)Person的prototype屬性中,構(gòu)造函數(shù)成了空函數(shù)。但是即便如此,我們也可以通過調(diào)用構(gòu)造函數(shù)來創(chuàng)建新對象,而且新對象還會具有相同的屬性和方法。
構(gòu)造函數(shù),實(shí)例對象和原型對象的關(guān)系實(shí)例對象就是通過構(gòu)造函數(shù)創(chuàng)造的,默認(rèn)擁有一個constructor屬性指向其構(gòu)造函數(shù)。
原型對象就是構(gòu)造函數(shù)的屬性prototype指向的那個對象,同時(shí)也是基于構(gòu)造函數(shù)生成的實(shí)例對象的原型對象。在默認(rèn)情況下,所有的原型對象都會自動獲得一個constructor屬性,這個屬性是一個指針,指向其構(gòu)造函數(shù)。
實(shí)例對象可以訪問原型對象上的屬性和方法。在實(shí)例對象的內(nèi)部有一個屬性(內(nèi)部屬性)[[Prototype]]指向其原型對象。有一種非標(biāo)準(zhǔn)方法__proto__訪問[[Prototype]]。
在上面的例子中person1和person2就是實(shí)例對象,構(gòu)造函數(shù)為Person,原型對象為Person.prototype。
來,看個栗子(還是上面那段代碼):
alert(person1.constructor === Person); // true alert(Person.prototype.constructor === Person); // true alerta(person1.__proto__ === Person.prototype); // true
來看個圖你就什么都懂了:
prototype是函數(shù)的一個默認(rèn)屬性,只有函數(shù)對象才有
Object.getPrototypeOf()方法用來返回實(shí)例對象內(nèi)部屬性[[prototype]]的值。這是ES5中定義的用來獲取原型對象的標(biāo)準(zhǔn)方法。
__proto__屬性是獲取原型對象的非標(biāo)準(zhǔn)方法(IE不支持)
看個栗子(還是上面那段代碼):
alert(Object.getPrototypeOf(person1) === Person.prototype); // true alert(Object.getPrototypeOf(person1).name); // "darko" alert(person1.__proto__ === Person.prototype); // true alert(person1.__proto__.name); // "darko"原型模式下的對象
每次查找對象的每個屬性,都是一次搜索。搜索從實(shí)例對象本身開始,如果在實(shí)例對象中找到,停止查找,返回值。如果沒有則繼續(xù)搜索實(shí)例對象指向的原型對象。
若實(shí)例對象中屬性和其指向的原型對象的屬性重名,實(shí)例對象中的屬性屏蔽原型對象中的那個屬性。
舉個栗子:
function Person(){}; Person.prototype.name = "darko"; Person.prototype.age = 21; Person.prototype.sayName = function(){ alert(this.name); } var person1 = new Person(); var person2 = new Person(); person1.name = "leon"; person1.sayName(); // "leon",來自實(shí)例 person2.sayName() // "darko",來自原型 delete person1.name; person1.sayName(); // "darko",來自原型
可以利用hasOwnProperty()方法判斷一個屬性是位于實(shí)例中,還是原型中。只有在屬性來自實(shí)例中時(shí),才會返回true。通常和in操作符配合使用。
// 接上 alert("name" in person1); // true alert(person1.hasOwnProperty("name")); // false原生對象的原型
所有的原生引用類型都在其原構(gòu)造函數(shù)的原型上定義了方法,例如,Array.prototype.sort()方法,正是由于原型的共享特性,我們定義的數(shù)組才可以使用sort()方法等一系列的方法。
舉個栗子:
var num = [1, 5, 3, 7, 9]; num.sort(); // 1,3,5,7,9 alert(num.constructor === Array); // true alert(num.__proto__ === Array.prototype); // true alert(num.__proto__.__proto__ === Object.prototype); //true
數(shù)組對象num本身就是構(gòu)造器Array的實(shí)例對象,而Array的prototype屬性指向的對象上定義了sort()方法,所以新定義了num對象經(jīng)過搜索找到了sort()方法,并調(diào)用了方法。
原型的動態(tài)性由于在原型中查找值的過程是一次搜索,所以對原型對象的任何修改都能立即從實(shí)例上反應(yīng)出來。
舉個栗子:
function Person(){}; var firend = new Person(); // 修改原型 Person.prototype.sayHi = function(){ alert("Hi"); } firend.sayHi(); // "Hi"
但是若將原型重寫,來看看有什么不同:
function Person(){}; Person.prototype.name = "darko"; var firend = new Person(); // 重寫了原型對象 Person.prototype = { constructor: Person, // 注意:重寫原型對象,所以此時(shí)的constructor屬性變成了新對象的構(gòu)造函數(shù),默認(rèn)為Object構(gòu)造函數(shù),應(yīng)該將其設(shè)置回適當(dāng)?shù)闹? sayHi: function(){ alert("Hi"); } } alert(friend.name); // "darko" firend.sayHi(); // error
這說明,重寫原型對象切斷了現(xiàn)有原型和任何之前已經(jīng)存在的實(shí)例對象之間的聯(lián)系,它們引用的仍是最初的原型。
如果你覺得我寫的還可以,點(diǎn)一下推薦吧。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/79187.html
摘要:不同于其他面向?qū)ο笳Z言,以前的中中沒有類的概念,主要是通過原型的方式來實(shí)現(xiàn)繼承,中引入了原型鏈,并且將原型鏈用來實(shí)現(xiàn)繼承,其核心是利用原型使得一個對象繼承另一個對象的方法和屬性,中原型繼承的關(guān)鍵是將一個實(shí)例的原型對象指向另一個實(shí)例,因此前一 不同于其他面向?qū)ο笳Z言,ES6以前的JavaScript中中沒有class類的概念,主要是通過原型的方式來實(shí)現(xiàn)繼承,JavaScript中引入了原...
摘要:原型對象內(nèi)部也有一個指針屬性指向構(gòu)造函數(shù)實(shí)例可以訪問原型對象上定義的屬性和方法。在創(chuàng)建子類型的實(shí)例時(shí),不能向超類型的構(gòu)造函數(shù)中傳遞參數(shù)。 贊助我以寫出更好的文章,give me a cup of coffee? 2017最新最全前端面試題 私有變量和函數(shù) 在函數(shù)內(nèi)部定義的變量和函數(shù),如果不對外提供接口,外部是無法訪問到的,也就是該函數(shù)的私有的變量和函數(shù)。 function ...
摘要:設(shè)計(jì)模式是以面向?qū)ο缶幊虨榛A(chǔ)的,的面向?qū)ο缶幊毯蛡鹘y(tǒng)的的面向?qū)ο缶幊逃行┎顒e,這讓我一開始接觸的時(shí)候感到十分痛苦,但是這只能靠自己慢慢積累慢慢思考。想繼續(xù)了解設(shè)計(jì)模式必須要先搞懂面向?qū)ο缶幊?,否則只會讓你自己更痛苦。 JavaScript 中的構(gòu)造函數(shù) 學(xué)習(xí)總結(jié)。知識只有分享才有存在的意義。 是時(shí)候替換你的 for 循環(huán)大法了~ 《小分享》JavaScript中數(shù)組的那些迭代方法~ ...
摘要:屬性是一個值或一組值以數(shù)組或?qū)ο蟮男问?,是對象的成員??梢允褂脙?nèi)置構(gòu)造函數(shù)和創(chuàng)建包裝對象。因此下面的代碼將會使人很迷惑結(jié)果結(jié)果,此數(shù)組長度為應(yīng)該盡量避免使用數(shù)組構(gòu)造函數(shù)創(chuàng)建新數(shù)組。給數(shù)組對象添加返回?cái)?shù)組中最大元素值的方法。 對象部分 Object類型 Object 是一個無序的集合,可以存放任意類型對象,所有其他對象都繼承自這個對象。創(chuàng)建Object類型有兩種,一種是使用new運(yùn)算符,...
摘要:從最開始的到封裝后的都在試圖解決異步編程過程中的問題。為了讓編程更美好,我們就需要引入來降低異步編程的復(fù)雜性。異步編程入門的全稱是前端經(jīng)典面試題從輸入到頁面加載發(fā)生了什么這是一篇開發(fā)的科普類文章,涉及到優(yōu)化等多個方面。 TypeScript 入門教程 從 JavaScript 程序員的角度總結(jié)思考,循序漸進(jìn)的理解 TypeScript。 網(wǎng)絡(luò)基礎(chǔ)知識之 HTTP 協(xié)議 詳細(xì)介紹 HTT...
閱讀 1354·2023-04-25 23:47
閱讀 929·2021-11-23 09:51
閱讀 4484·2021-09-26 10:17
閱讀 3735·2021-09-10 11:19
閱讀 3269·2021-09-06 15:10
閱讀 3557·2019-08-30 12:49
閱讀 2438·2019-08-29 13:20
閱讀 1743·2019-08-28 18:14