JavaScript prototype對(duì)象的屬性說(shuō)明
一、什么是JavaScript中對(duì)象的prototype屬性
JavaScript中對(duì)象的prototype屬性,是用來(lái)返回對(duì)象類型原型的引用的。我們使用prototype屬性提供對(duì)象的類的一組基本功能。并且對(duì)象的新實(shí)例會(huì)”繼承”賦予該對(duì)象原型的操作。但是這個(gè)prototype到底是怎么實(shí)現(xiàn)和被管理的呢?
對(duì)于對(duì)象的prototype屬性的說(shuō)明,JavaScript手冊(cè)上如是說(shuō):所有 JavaScript內(nèi)部對(duì)象都有只讀的 prototype 屬性??梢韵蚱湓椭袆?dòng)態(tài)添加功能(屬性和方法),但該對(duì)象不能被賦予不同的原型。然而,用戶定義的對(duì)象可以被賦給新的原型。
在JavaScript中,prototype對(duì)象是實(shí)現(xiàn)面向?qū)ο蟮囊粋€(gè)重要機(jī)制。每個(gè)函數(shù)就是一個(gè)對(duì)象(Function),函數(shù)對(duì)象都有一個(gè)子對(duì)象prototype對(duì)象,類是以函數(shù)的形式來(lái)定義的。prototype表示該函數(shù)的原型,也表示一個(gè)類的成員的集合。在通過(guò)new創(chuàng)建一個(gè)類的實(shí)例對(duì)象的時(shí)候,prototype對(duì)象的成員都成為實(shí)例化對(duì)象的成員。
1、該對(duì)象被類所引用,只有函數(shù)對(duì)象才可引用;
2、在new實(shí)例化后,其成員被實(shí)例化,實(shí)例對(duì)象方可調(diào)用。
同時(shí),函數(shù)是一個(gè)對(duì)象,函數(shù)對(duì)象若直接聲明成員,不用被實(shí)例化即可調(diào)用。
JavaScript通過(guò)一種鏈接機(jī)制來(lái)支持繼承,而不是通過(guò)完全面向?qū)ο笳Z(yǔ)言(如Java)所支持的基于類的繼承模型。每個(gè)JavaScript對(duì)象都有一個(gè)內(nèi)置的屬性,名為prototype。prototype屬性保存著對(duì)另一個(gè)JavaScript對(duì)象的引用,這個(gè)對(duì)象作為當(dāng)前對(duì)象的父對(duì)象。
當(dāng)通過(guò)點(diǎn)記法引用對(duì)象的一個(gè)函數(shù)或?qū)傩詴r(shí),倘若對(duì)象上沒(méi)有這個(gè)函數(shù)或?qū)傩?,此時(shí)就會(huì)使用對(duì)象的prototype屬性。當(dāng)出現(xiàn)這種情況時(shí),將檢查對(duì)象prototype屬性所引用的對(duì)象,查看是否有所請(qǐng)求的屬性或函數(shù)。如果prototype屬性引用的對(duì)象也沒(méi)有所需的函數(shù)或?qū)傩裕瑒t會(huì)進(jìn)一步檢查這個(gè)對(duì)象(prototype屬性引用的對(duì)象)的prototype屬性,依次沿著鏈向上查找,直到找到所請(qǐng)求的函數(shù)或?qū)傩?,或者到達(dá)鏈尾,如果已經(jīng)到達(dá)鏈尾還沒(méi)有找到,則返回undefined。從這個(gè)意義上講,這種繼承結(jié)構(gòu)更應(yīng)是一種“has a”關(guān)系,而不是“is a”關(guān)系
神啊,我什么也看懂,怎么辦?看似搞得我很牛,說(shuō)實(shí)話我也看不懂!^_^ ^_^ ^_^
二、prototype屬性應(yīng)用實(shí)例
我們所常見(jiàn)的類包括:數(shù)組變量(Array)、邏輯變量(Boolean)、日期變量(Date)、結(jié)構(gòu)變量(Function)、數(shù)值變量(Number)、對(duì)象變量(Object)、字符串變量(String) 等,而相關(guān)的類的方法,也是程序員經(jīng)常用到的(在這里要區(qū)分一下類的注意和屬性發(fā)方法),例如數(shù)組的push方法、日期的get系列方法、字符串的split方法等等,
但是在實(shí)際的編程過(guò)程中不知道有沒(méi)有感覺(jué)到現(xiàn)有方法的不足?prototype 方法應(yīng)運(yùn)而生!下面,將通過(guò)實(shí)例由淺入深講解 prototype 的具體使用方法:
先看一個(gè)很傻的例子:
JavaScript代碼
function func(){
func.prototype.name = “prototype of func”;
}
var f = new func();
alert(f.name); //prototype of func
先創(chuàng)建一個(gè)func對(duì)象,設(shè)置func對(duì)象的name屬性,實(shí)例化f;
1.幾個(gè)簡(jiǎn)單的例子:
(1)數(shù)字相加:
JavaScript代碼
Number.prototype.add=function(num){
return (this+num);//這里的this指向Number
};
alert((3).add(15));//18
(2) Boolean.rev(): 作用,布爾變量取反
實(shí)現(xiàn)方法:Boolean.prototype.rev = function(){return(!this);}
試驗(yàn):alert((true).rev()) -> 顯示 false
2、已有方法的實(shí)現(xiàn)和增強(qiáng),初識(shí) prototype:
(1) Array.push(new_element)
作用:在數(shù)組末尾加入一個(gè)新的元素
實(shí)現(xiàn)方法:
Array.prototype.push = function(new_element){
this[this.length]=new_element;
return this.length;
}
讓我們進(jìn)一步來(lái)增強(qiáng)他,讓他可以一次增加多個(gè)元素!
實(shí)現(xiàn)方法:
Array.prototype.pushPro = function() {
var currentLength = this.length;
for (var i = 0; i < arguments.length; i++) {
this[currentLength + i] = arguments[i];
}
return this.length;
}
應(yīng)該不難看懂吧?以此類推,你可以考慮一下如何通過(guò)增強(qiáng) Array.pop 來(lái)實(shí)現(xiàn)刪除任意位置,任意多個(gè)元素(具體代碼就不再細(xì)說(shuō)了)
3、新功能的實(shí)現(xiàn),深入 prototype:在實(shí)際編程中所用到的肯定不只是已有方法的增強(qiáng),更多的實(shí)行的功能的要求,下面我就舉兩個(gè)用 prototype 解決實(shí)際問(wèn)題的例子:
(1) String.left()
問(wèn)題:用過(guò) vb 的應(yīng)該都知道left函數(shù),從字符串左邊取 n 個(gè)字符,但是不足是將全角、半角均視為是一個(gè)字符,造成在中英文混排的版面中不能截取等長(zhǎng)的字符串
作用:從字符串左邊截取 n 個(gè)字符,并支持全角半角字符的區(qū)分
實(shí)現(xiàn)方法:
String.prototype.left = function(num,mode){
if(!/\d+/.test(num))return(this);
var str = this.substr(0,num);
if(!mode) return str;
var n = str.Tlength() – str.length;
num = num – parseInt(n/2);
return this.substr(0,num);
}
試驗(yàn):alert(“aa啦啦aa”.left(4)) -> 顯示 aa啦啦
alert(“aa啦啦aa”.left(4,true)) -> 顯示 aa啦
本方法用到了上面所提到的String.Tlength()方法,自定義方法之間也能組合出一些不錯(cuò)的新方法呀!
(2) Date.DayDiff()
作用:計(jì)算出兩個(gè)日期型變量的間隔時(shí)間(年、月、日、周)
實(shí)現(xiàn)方法:
Date.prototype.DayDiff = function(cDate,mode){
try{
cDate.getYear();
}catch(e){
return(0);
}
var base =60*60*24*1000;
var result = Math.abs(this – cDate);
switch(mode){
case “y”:
result/=base*365;
break;
case “m”:
result/=base*365/12;
break;
case “w”:
result/=base*7;
break;
default:
result/=base;
break;
}
return(Math.floor(result));
}
試驗(yàn):alert((new Date()).DayDiff((new Date(2002,0,1)))) -> 顯示 329
alert((new Date()).DayDiff((new Date(2002,0,1)),”m”)) -> 顯示 10
當(dāng)然,也可以進(jìn)一步擴(kuò)充,得出響應(yīng)的小時(shí)、分鐘,甚至是秒。
(3) Number.fact()
作用:某一數(shù)字的階乘
實(shí)現(xiàn)方法:
Number.prototype.fact=function(){
var num = Math.floor(this);
if(num<0)return NaN;
if(num==0 || num==1)
return 1;
else
return (num*(num-1).fact());
}
試驗(yàn):alert((4).fact()) -> 顯示 24
這個(gè)方法主要是說(shuō)明了遞歸的方法在 prototype 方法中也是可行的!
實(shí)例:
取數(shù)組的最大值:
JavaScript代碼
var oArr=new Array();
oArr=[100,190,199,189,3000,400,4001];
Array.prototype.MAX=function(){
var i,max=this[0];
for(i=1;i<this.length;i++){
if(max<this[i]){
max=this[i];
}
}
return max;
}
alert(oArr.MAX());
實(shí)例為用戶自定義類添加方法:
JavaScript代碼
function TestObject()
{
this.m_Name = “ffffffffff”;
}
TestObject.prototype.ShowName = function()
{
alert(this.m_Name);
};
var f=new TestObject();
f.ShowName();
更新自定義類的prototype:
JavaScript代碼
function TestObjectA()
{
this.MethodA = function()
{
alert(‘TestObjectA.MethodA()');
}
}
function TestObjectB()
{
this.MethodB = function()
{
alert(‘TestObjectB.MethodB()');
}
}
TestObjectB.prototype = new TestObjectA();
聽(tīng)說(shuō)這是錯(cuò)說(shuō)中的繼承;哦以后慢慢學(xué)。
再看一個(gè)例子,估計(jì)你我都已經(jīng)瘋掉了:
JavaScript代碼
function RP()
{
RP.PropertyA = 1;
RP.MethodA = function()
{
alert(“RP.MethodA ”);
};
this.PropertyA = 100;
this.MethodA = function()
{
alert(“this.MethodA”);
};
}
RP.prototype.PropertyA = 10;
RP.prototype.MethodA = function()
{
alert(“RP.prototype.MethodA”);
};
//以下執(zhí)行
rp = new RP();
alert(RP.PropertyA);//警告結(jié)果為:1
RP.MethodA();//警告結(jié)果為:RP.MethodA
alert(rp.PropertyA);//警告結(jié)果為:100
rp.MethodA();//警告結(jié)果為:this.MethodA
delete RP.PropertyA;
alert(RP.PropertyA);//警告結(jié)果為:undefined
delete rp.PropertyA;
alert(rp.PropertyA);//警告結(jié)果為:100
delete rp.MethodA;
rp.MethodA();//警告結(jié)果為:RP.prototype.MethodA
再看一個(gè)帶有參數(shù)的,計(jì)算圓的面積:
JavaScript代碼
<script type=“text/javascript”>
function Circle(x,y,r){
this.x = x;
this.y = y;
this.r = r;
//this.prototype = null ; /*這句代碼可以看作是隱含存在的,因?yàn)閖avascript 中“類”的定義和函數(shù)的定義結(jié)構(gòu)上沒(méi)有差異,所以可以說(shuō),所有函數(shù)都隱藏有這樣一個(gè)屬性。*/
}
Circle.prototype.area=function(){
return this.r*this.r*3.1415926;
}
var Circ=new Circle(0,0,5);
alert(parseInt(Circ.area()));
</script>
- JavaScript為對(duì)象原型prototype添加屬性的兩種方式
- js使用原型對(duì)象(prototype)需要注意的地方
- [js高手之路]圖解javascript的原型(prototype)對(duì)象,原型鏈實(shí)例
- javascript當(dāng)中的代碼嗅探擴(kuò)展原生對(duì)象和原型(prototype)
- JS 面向?qū)ο笾衿娴膒rototype
- JS面向?qū)ο?、prototype、call()、apply()
- javascript Prototype 對(duì)象擴(kuò)展
- JavaScript面向?qū)ο笾甈rototypes和繼承
- JavaScript中prototype為對(duì)象添加屬性的誤區(qū)介紹
- javascript 對(duì)象 與 prototype 原型用法實(shí)例分析
相關(guān)文章
ES6知識(shí)點(diǎn)整理之函數(shù)對(duì)象參數(shù)默認(rèn)值及其解構(gòu)應(yīng)用示例
這篇文章主要介紹了ES6知識(shí)點(diǎn)整理之函數(shù)對(duì)象參數(shù)默認(rèn)值及其解構(gòu)應(yīng)用,結(jié)合實(shí)例形式分析了ES6函數(shù)對(duì)象參數(shù)相關(guān)使用技巧,需要的朋友可以參考下2019-04-04php簡(jiǎn)單數(shù)據(jù)庫(kù)操作類的封裝
這篇文章主要為大家詳細(xì)介紹了php簡(jiǎn)單數(shù)據(jù)庫(kù)操作類的封裝,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-06-0680行代碼寫(xiě)一個(gè)Webpack插件并發(fā)布到npm
最近在學(xué)習(xí) Webpack 相關(guān)的原理,本文用80行代碼寫(xiě)一個(gè)Webpack插件并發(fā)布到npm,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-05-05Node.js實(shí)戰(zhàn) 建立簡(jiǎn)單的Web服務(wù)器
本章我們同樣通過(guò)實(shí)戰(zhàn)的演練,利用Node.js建立一個(gè)簡(jiǎn)單的Web服務(wù)器2012-03-03JavaScrip簡(jiǎn)單數(shù)據(jù)類型隱式轉(zhuǎn)換的實(shí)現(xiàn)
本文主要介紹了JavaScrip簡(jiǎn)單數(shù)據(jù)類型隱式轉(zhuǎn)換的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-05-05