欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

javascript的函數(shù)、創(chuàng)建對(duì)象、封裝、屬性和方法、繼承

 更新時(shí)間:2011年03月10日 23:32:00   作者:  
從一開(kāi)始接觸到j(luò)s就感覺(jué)好靈活,每個(gè)人的寫法都不一樣,比如一個(gè)function就有N種寫法
一,function
從一開(kāi)始接觸到j(luò)s就感覺(jué)好靈活,每個(gè)人的寫法都不一樣,比如一個(gè)function就有N種寫法
如:function showMsg(){},var showMsg=function(){},showMsg=function(){}
似乎沒(méi)有什么區(qū)別,都是一樣的嘛,真的是一樣的嗎,大家看看下面的例子
復(fù)制代碼 代碼如下:

///-----------------------------------------------------------------------------------------

-------
//函數(shù)定義:命名函數(shù)(聲明式),匿名函數(shù)(引用式)
//聲明式,定義代碼先于函數(shù)執(zhí)行代碼被解析
function t1(){
dwn("t1");
}
t1();
function t1(){
dwn("new t1");
}
t1();
//引用式,在函數(shù)運(yùn)行中進(jìn)行動(dòng)態(tài)解析
var t1=function(){
dwn("new new t1");
}
t1();
var t1=function(){
dwn("new new new t1");
}
t1();
//以上輸出:new t1,new t1,new new t1,new new new t1

可能想著應(yīng)該是輸出t1,new t1,new newt1,new new new t1,結(jié)果卻并不是這樣,應(yīng)該理解這句話:聲明

式,定義代碼先于函數(shù)執(zhí)行代碼被解析
如果深入一步,應(yīng)該說(shuō)是scope鏈問(wèn)題,實(shí)際上前面兩個(gè)方法等價(jià)于window.t1,可以理解為t1是window的

一個(gè)公有屬性,被賦了兩次值,以最后一次賦值為最終值
而后面兩個(gè)方法,可以理解為是t1是個(gè)變量,第四個(gè)方法的var去掉之后的結(jié)果仍然不會(huì)改變
然而,當(dāng)?shù)谒膫€(gè)方法改成function t1(){}這樣的聲明式時(shí),結(jié)果變成了new new new t1,new new new

t1,new new t1,new new t1
前面兩個(gè)按照我的理解可以很好的理解為什么是這個(gè)答案,第三個(gè)也可以理解,但是最后一個(gè)輸出讓我比

較糾結(jié),希望有高手出現(xiàn)解答一下
另外匿名函數(shù)還有(function(){...})()這樣的寫法,最后一個(gè)括號(hào)用于參數(shù)輸入
還有var t1=new function(){..}這樣的聲明,實(shí)際上t1已經(jīng)是一個(gè)對(duì)象了
例:
復(fù)制代碼 代碼如下:

var t2 = new function()
{
var temp = 100; //私有成員
this.temp = 200; //公有成員,這兩個(gè)概念會(huì)在第三點(diǎn)以后展開(kāi)說(shuō)明
return temp + this.temp;
}

alert(typeof(t2)); //object
alert(t2.constructor()); //300
除此之外,還有使用系統(tǒng)內(nèi)置函數(shù)對(duì)象來(lái)構(gòu)建一個(gè)函數(shù),例:
var t3 = new Function('var temp = 100; this.temp = 200; return temp + this.temp;'); //這個(gè)位置加不加new結(jié)果都一樣,WHY
alert(typeof(t3)); //function
alert(t3()); //300

二,創(chuàng)建對(duì)象
首先我們理解一下面向?qū)ο缶幊蹋∣bject-Oriented Programming,OOP),使用OOP技術(shù),常常要使用許多

代碼模塊,每個(gè)模塊都提供特定的功能,每個(gè)模塊都是孤立的,甚至與其它模塊完全獨(dú)立
。這種模塊化編程方法提供了非常大的多樣性,大大增加了代碼的重用機(jī)會(huì)??梢耘e例進(jìn)一步說(shuō)明這個(gè)問(wèn)

題,假定計(jì)算機(jī)上的一個(gè)高性能應(yīng)用程序是一輛一流賽車。如果使用傳統(tǒng)的編程技巧,這輛賽車就是
一個(gè)單元。如果要改進(jìn)該車,就必須替換整個(gè)單元,把它送回廠商,讓汽車專家升級(jí)它,或者購(gòu)買一個(gè)新

車。如果使用OOP技術(shù),就只需從廠商處購(gòu)買新的引擎,自己按照說(shuō)明替換它,而不必用鋼鋸切割車體。
不過(guò)大部分的論點(diǎn)是,javascript并不是直接的面向?qū)ο蟮恼Z(yǔ)言,但是通過(guò)模擬可以做到很多面向?qū)ο笳Z(yǔ)

言才能做到的事,如繼承,多態(tài),封裝,javascript都能干(沒(méi)有做不到,只是想不到)
復(fù)制代碼 代碼如下:

///-----------------------------------------------------------------------------------------

-------
//以下三種構(gòu)造對(duì)象的方法
//new Object,實(shí)例化一個(gè)Object
var a=new Object();
a.x=1,a.y=2;
//對(duì)象直接量
var b={x:1,y:2};
//定義類型
function Point(x,y){ //類似于C#中的類
this.x=x;
this.y=y;
}
var p=new Point(1,2); //實(shí)例化類

第一種方法通過(guò)構(gòu)造基本對(duì)象直接添加屬性的方法來(lái)實(shí)現(xiàn),第二種和第一種差不多,可以看成是第一種方

法的快捷表示法
第三種方法中,可以以”類“為基礎(chǔ),創(chuàng)造多個(gè)類型相同的對(duì)象

三,對(duì)象屬性的封裝(公有和私有)
以例子來(lái)說(shuō)明
function List(){
var m_elements=[]; //私有成員,在對(duì)象外無(wú)法訪問(wèn),如果此處無(wú)var聲明,則m_elements將變成全局變

量,這樣外部是可以直接訪問(wèn)到的,如alert(m_elements[0])
復(fù)制代碼 代碼如下:

m_elements=Array.apply(m_elements,arguments);
//此處模擬getter,使用時(shí)alist.length;
//等價(jià)于getName()方式:this.length=function(){return m_elements.length;},使用時(shí)

alist.length();
//公有屬性,可以通過(guò)"."運(yùn)算符或下標(biāo)來(lái)訪問(wèn)
this.length={
valueOf:function(){
return m_elements.length;
},
toString:function(){
return m_elements.length;
}
}
//公有方法,此方法使用得alert(alist)相當(dāng)于alert(alist.toString())
this.toString=function(){
return m_elements.toString();
}
//公有方法
this.add=function(){
m_elements.push.apply(m_elements,arguments);
}
//私有方法如下形式,這里涉及到了閉包的概念,接下來(lái)繼續(xù)說(shuō)明
//var add=function()或function add()
//{
//m_elements.push.apply(m_elements,arguments);
//}
}
var alist=new List(1,2,3);
dwn(alist); //=alert(alist.toString()),輸出1,2,3
dwn(alist.length); //輸出3
alist.add(4,5,6);
dwn(alist); //輸出1,2,3,4,5,6
dwn(alist.length); //輸出6

四,屬性和方法的類型
javascript里,對(duì)象的屬性和方法支持4種不同的類型:private property(私有屬性),dynamic public

property(動(dòng)態(tài)公有屬性),static public property/prototype property(靜態(tài)公有屬性或原型屬性),
static property(靜態(tài)屬性或類屬性)。私有屬性對(duì)外界完全不具備訪問(wèn)性,可以通過(guò)內(nèi)部的getter和

setter(都是模擬);動(dòng)態(tài)公有屬性外界可以訪問(wèn),每個(gè)對(duì)象實(shí)例持有一個(gè)副本,不會(huì)相互影響;原型
屬性每個(gè)對(duì)象實(shí)例共享唯一副本;類屬性不作為實(shí)例的屬性,只作為類的屬性。
以下是例子:
復(fù)制代碼 代碼如下:

///-----------------------------------------------------------------------------------------

-------
//動(dòng)態(tài)公有類型,靜態(tài)公有類型(原型屬性)
function myClass(){
var p=100; //private property
this.x=10; //dynamic public property
}
myClass.prototype.y=20; //static public property or prototype property,動(dòng)態(tài)為myClass的原型添

加了屬性,將作用于所有實(shí)例化了的對(duì)象,注意這里用到了prototype,這是一個(gè)非常有用的東東
//要想成為高級(jí)javascript階段,prototype和閉包必須得理解和適當(dāng)應(yīng)用
myClass.z=30; //static property

var a=new myClass();
dwn(a.p) //undefined
dwn(a.x) //10
dwn(a.y) //20
a.x=20;
a.y=40;
dwn(a.x); //20
dwn(a.y); //40
delete(a.x); //刪除對(duì)象a的屬性x
delete(a.y); //刪除對(duì)象a的屬性y
dwn(a.x); //undefined
dwn(a.y); //20 靜態(tài)公有屬性y被刪除后還原為原型屬性y
dwn(a.z); //undefined 類屬性無(wú)法通過(guò)對(duì)象訪問(wèn)
dwn(myClass.z);

五,原型(prototype)
這里只講部分,prototype和閉包都不是幾句話都能講清楚的,如果這里可以給你一些啟蒙,則萬(wàn)幸矣
習(xí)語(yǔ)”照貓畫虎“,這里的貓就是原型,虎是類型,可以表示成:虎.prototype=某只貓 or

虎.prototype=new 貓()
因?yàn)樵蛯傩悦總€(gè)對(duì)象實(shí)例共享唯一副本,所以當(dāng)實(shí)例中的一個(gè)調(diào)整了一個(gè)原型屬性的值時(shí),所有實(shí)例調(diào)

用這個(gè)屬性時(shí)都將發(fā)生變化,這點(diǎn)需要注意
以下是原型關(guān)系的類型鏈:
復(fù)制代碼 代碼如下:

function ClassA(){
}
ClassA.prototype=new Object();
function ClassB(){
}
ClassB.prototype=new ClassA();
function ClassC(){
}
ClassC.prototype=new ClassB();
var obj=new ClassC();
dwn(obj instanceof ClassC); //true
dwn(obj instanceof ClassB); //true
dwn(obj instanceof ClassA); //true
dwn(obj instanceof Object); //true
帶默認(rèn)值的Point對(duì)象:
function Point2(x,y){
if (x) this.x=x;
if (y) this.y=y;
}
//設(shè)定Point2對(duì)象的x,y默認(rèn)值為0
Point2.prototype.x=0;
Point2.prototype.y=0;
//p1是一個(gè)默認(rèn)(0,0)的對(duì)象
var p1=new Point2(); //可以寫成var p1=new Point2也不會(huì)出錯(cuò),WHY
//p2賦值
var p2=new Point2(1,2);
dwn(p1.x+","+p1.y); //0,0
dwn(p2.x+","+p2.y); //1,2
delete對(duì)象的屬性后,原型屬性將回到初始化的狀態(tài):
function ClassD(){
this.a=100;
this.b=200;
this.c=300
}
ClassD.prototype=new ClassD(); //將ClassD原有的屬性設(shè)為原型,包括其值
ClassD.prototype.reset=function(){ //將非原型屬性刪除
for (var each in this) {
delete this[each];
}
}
var d=new ClassD();
dwn(d.a); //100
d.a*=2;
d.b*=2;
d.c*=2;
dwn(d.a); //200
dwn(d.b); //400
dwn(d.c); //600
d.reset(); //刪掉非原型屬性,所有回來(lái)原型
dwn(d.a); //100
dwn(d.b); //200
dwn(d.c); //300

六,繼承
如果兩個(gè)類都是同一個(gè)實(shí)例的類型,那么它們之間存在著某種關(guān)系,我們把同一個(gè)實(shí)例的類型之間的泛化

關(guān)系稱為繼承。C#和JAVA中都有這個(gè),具體的理解就不說(shuō)了。
在javascript中,并不直接從方法上支持繼承,但是就像前面說(shuō)的,可以模擬啊
方法可以歸納為四種:構(gòu)造繼承法,原型繼承法,實(shí)例繼承法和拷貝繼承法。融會(huì)貫通之后,還有混合繼

續(xù)法,這是什么法,就是前面四種挑幾種混著來(lái)~
以下例子來(lái)源于王者歸來(lái),其中涉及到了apply,call和一些Array的用法,有興趣的可以自己在園子里搜索

一下
1,構(gòu)造繼續(xù)法例子:
復(fù)制代碼 代碼如下:

//定義一個(gè)Collection類型
function Collection(size)
{
this.size = function(){return size}; //公有方法,可以被繼承
}

Collection.prototype.isEmpty = function(){ //靜態(tài)方法,不能被繼承
return this.size() == 0;
}

//定義一個(gè)ArrayList類型,它"繼承"Collection類型
function ArrayList()
{
var m_elements = []; //私有成員,不能被繼承
m_elements = Array.apply(m_elements, arguments);

//ArrayList類型繼承Collection
this.base = Collection;
this.base.call(this, m_elements.length);

this.add = function()
{
return m_elements.push.apply(m_elements, arguments);
}
this.toArray = function()
{
return m_elements;
}
}

ArrayList.prototype.toString = function()
{
return this.toArray().toString();
}
//定義一個(gè)SortedList類型,它繼承ArrayList類型
function SortedList()
{
//SortedList類型繼承ArrayList
this.base = ArrayList;
this.base.apply(this, arguments);

this.sort = function()
{
var arr = this.toArray();
arr.sort.apply(arr, arguments);
}
}

//構(gòu)造一個(gè)ArrayList
var a = new ArrayList(1,2,3);
dwn(a);
dwn(a.size()); //a從Collection繼承了size()方法
dwn(a.isEmpty); //但是a沒(méi)有繼承到isEmpty()方法

//構(gòu)造一個(gè)SortedList
var b = new SortedList(3,1,2);
b.add(4,0); //b 從ArrayList繼承了add()方法
dwn(b.toArray()); //b 從ArrayList繼承了toArray()方法
b.sort(); //b 自己實(shí)現(xiàn)的sort()方法
dwn(b.toArray());
dwn(b);
dwn(b.size()); //b從Collection繼承了size()方法

2,原型繼承法例子:
復(fù)制代碼 代碼如下:

//定義一個(gè)Point類型
function Point(dimension)
{

this.dimension = dimension;
}

//定義一個(gè)Point2D類型,"繼承"Point類型
function Point2D(x, y)
{
this.x = x;
this.y = y;
}
Point2D.prototype.distance = function()
{
return Math.sqrt(this.x * this.x + this.y * this.y);
}
Point2D.prototype = new Point(2); //Point2D繼承了Point

//定義一個(gè)Point3D類型,也繼承Point類型
function Point3D(x, y, z)
{
this.x = x;
this.y = y;
this.z = z;
}
Point3D.prototype = new Point(3); //Point3D也繼承了Point

//構(gòu)造一個(gè)Point2D對(duì)象
var p1 = new Point2D(0,0);
//構(gòu)造一個(gè)Point3D對(duì)象
var p2 = new Point3D(0,1,2);

dwn(p1.dimension);
dwn(p2.dimension);
dwn(p1 instanceof Point2D); //p1 是一個(gè) Point2D
dwn(p1 instanceof Point); //p1 也是一個(gè) Point
dwn(p2 instanceof Point); //p2 是一個(gè)Point

以上兩種方法是最常用的
3,實(shí)例繼承法例子:
在說(shuō)此法例子之前,說(shuō)說(shuō)構(gòu)造繼承法的局限,如下:
復(fù)制代碼 代碼如下:

function MyDate()
{
this.base = Date;
this.base.apply(this, arguments);
}
var date = new MyDate();
alert(date.toGMTString); //undefined,date并沒(méi)有繼承到Date類型,所以沒(méi)有toGMTString方法

核心對(duì)象的某些方法不能被構(gòu)造繼承,原因是核心對(duì)象并不像我們自定義的一般對(duì)象那樣在構(gòu)造函數(shù)里進(jìn)

行賦值或初始化操作
換成原型繼承法呢?,如下:
復(fù)制代碼 代碼如下:

function MyDate(){}
MyDate.prototype=new Date();
var date=new MyDate();
alert(date.toGMTString); //'[object]'不是日期對(duì)象,仍然沒(méi)有繼承到Date類型!

現(xiàn)在,換成實(shí)例繼承法:
復(fù)制代碼 代碼如下:

function MyDate()
{
var instance = new Date(); //instance是一個(gè)新創(chuàng)建的日期對(duì)象
instance.printDate = function(){
document.write("<p> "+instance.toLocaleString()+"</p> ");
} //對(duì)instance擴(kuò)展printDate()方法
return instance; //將instance作為構(gòu)造函數(shù)的返回值返回
}
var myDate = new MyDate();
dwn(myDate.toGMTString()); //這回成功輸出了正確的時(shí)間字符串,看來(lái)myDate已經(jīng)是一個(gè)Date的實(shí)例

了,繼承成功
myDate.printDate(); //如果沒(méi)有return instance,將不能以下標(biāo)訪問(wèn),因?yàn)槭撬接袑?duì)象的方法
4,拷貝繼承法例子:
復(fù)制代碼 代碼如下:

Function.prototype.extends = function(obj)
{
for(var each in obj)
{
this.prototype[each] = obj[each];
//對(duì)對(duì)象的屬性進(jìn)行一對(duì)一的復(fù)制,但是它又慢又容易引起問(wèn)題
//所以這種“繼承”方式一般不推薦使用
}
}
var Point2D = function(){
//……
}
Point2D.extends(new Point())
{
//……
}

這種繼承法似乎是用得很少的。
5,混合繼承例子:
復(fù)制代碼 代碼如下:

function Point2D(x, y)
{
this.x = x;
this.y = y;
}
function ColorPoint2D(x, y, c)
{
Point2D.call(this, x, y); //這里是構(gòu)造繼承,調(diào)用了父類的構(gòu)造函數(shù)
//從前面的例子看過(guò)來(lái),這里等價(jià)于
//this.base=Point2D;
//this.base.call(this,x,y);
this.color = c;
}
ColorPoint2D.prototype = new Point2D(); //這里用了原型繼承,讓ColorPoint2D以Point2D對(duì)象為原型


相關(guān)文章

最新評(píng)論