網頁制作poluoluo文章簡介:JS教程:學習筆記之JS類.
背景:接觸JavaScript快兩年了。從最開始對她充滿著好奇,到現在的學習了許多關於她的框架。朋友問我:都有這麼多框架,你為何還要去學最底層的面向對象呢?其實這個問題:另一個朋友已經替我回答了。無論以後框架在怎麼變,只要了解底層的原理,學起來都是很容易上手的。好了,我們開始學習了。
1、 創建對象:
var obj = new Object();//第一種方式。
var obj = {};//第二種方法。順帶一句可以通過var arr = [] 來創建數組
2、 給對象的屬性賦值
nahao.gender = 'male';
nahao.yearOfBirth = 1989;
nahao.name = 'Topcss'; //對象的屬性也可以叫做對象的成員。像普通的變量一樣,JS對象的屬性可以是是字符串,數組,數字,甚至可以是對象或者是函數。
3、 給對象添加方法其實對象的屬性如果是函數,那麼這個屬性就可以叫做對象的方法
nahao.gender = 'male';
nahao.yearOfBirth = 1989;
nahao.name = 'Topcss';
nahao.info = function(){
var str = '姓名:' +
this.name + ',性別:' +
this.gender + ',出生年:' +
this.yearOfBirth;
alert(str);
}
nahao.info();
4、 我們可以使用下面的簡略語法定義上面的對象:
var nahao = {
gender : 'male',
yearOfBirth : 1989,
name : 'Topcss',
info : function(){
var str = '姓名:' + this.name + ',性別:' + this.gender + ',出生年:' + this.yearOfBirth;
alert(str);
}
};//如果調用nahao.info(),將會得到和上面一樣的結果。需要注意的是,屬性之間使用逗號隔開,最後一個屬性之後沒有逗號。
5、 構造函數構造函數可以幫助我們來縮減代碼量。首先,構造函數也是一個函數。雛形如下:
function Person(){}/和定義普通的函數沒有什麼區別。下面就來向Person構造函數中添加內容:
function Person(name,gender,yearOfBirth,site){
this.name = name;
this.gender = gender;
this.yearOfBirth = yearOfBirth;
this.site = site;
this.info = function(){
var str = '姓名:' + this.name + ',性別:' + this.gender
+ ',出生年:' + this.yearOfBirth + '網站:' + this.site;
alert(str);
}
}//這樣,構造函數就完成了。我們現在就可以使用如下語句來定義多個對象了:
var nahao = new Person('Top css',male,1989,'www.javava.org);
var gaoshou = new Person('Widen','male',1980,'www.baidu.net');
var wudi = new Person('不詳','不知道','保密','bbs.blueidea.net');通過他們的方法來調用
nahao.info();
gaoshou.info();
wudi.info();
注意:在上面的構造函數中,參數的名字和對象屬性的名字是相同的,例如:
this.name = name;雖然這樣是合法的,但是如果要定義私有屬性的話就不行了(後面會提),而且看起來比較混亂。所以最好將構造函數修改如下:
function Person(nameArg,genderArg,yearOfBirthArg,siteArg){
this.name = nameArg;
this.gender = genderArg;
this.yearOfBirth = yearOfBirthArg;
this.site = siteArg;
this.info = function(){
var str = '姓名:' + this.name + ',性別:' + this.gender
+ ',出生年:' + this.yearOfBirth + '網站:' + this.site;
alert(str);
}
}
6、 靜態方法什麼是靜態方法呢?就是直接添加在某個對象上的屬性或者方法,它僅對一個對象有效,例如:
nahao.skill = '會點XHTML,CSS,現在還會說JavaScript了';添加完這個語句之後,nahao就擁有了skill屬性。但是出自同一個構造函數的gaoshou和wudi卻不受任何影響。當然了,我們可以給它們也加上這個屬性:
gaoshou.skill = '精通HTML,CSS,JS,FLEX,PHP,.NET,Linux編程,Perl,Ruby,XXX...';
wudi.skill = '能用啤酒瓶蓋與沙子手工打磨出CPU等PC基本零部件。';
同樣,我們也可以給構造函數添加靜態方法,但是這同樣不會影響使用該構造函數定義的對象。例如:
Person.showName = function(){
alert(this.name);
};
Person.showName();
nahao.showName();//我們給Person定義了一個showName函數,但是它只對構造函數Person本身有用(但是沒有什麼實際意義),如果在nahao對象上調用這個方法將會出錯。
7、 給對象定義私有成員公開的對象?在前面定義的所有對象,其所有的屬性都是暴露在外的,可以隨便訪問,甚至修改也沒問題。例如我們可以通過nahao.name直接訪問到對象的名字等等屬性。如果我們希望有一個屬性對外保密,就可以給對象定義私有屬性:
function Person(nameArg,genderArg,yearOfBirthArg,siteArg,privacyArg){
……
var privacy = privacyArg;
……
}
var nahao = new Person('Top css',male,1989,'www.javava.org','有10跟腳趾頭');
alert(nahao.privacy); //對構造函數作出一定修改之後,我們給nahao對象添加了一個privacy屬性,如果試圖alert它的值的話將會顯示undefined。
下面再來看看私有方法,如果我們對Person構造函數作出如下修改:
function Person(nameArg,genderArg,yearOfBirthArg,siteArg,privacyArg){
function insideOnly(){
alert('我只在對象內部可以調用!');
}
}//那麼insideOnly將不能被外部所訪問,如果試圖執行這個函數將會出錯。需要注意的是,私有方法並沒有綁定到對象上,它的this關鍵字也並不指向對象。如果需要在私有方法內引用對象,那麼可以使用如下方法:
function Person(nameArg,genderArg,yearOfBirthArg,siteArg,privacyArg){
……
var myOwner = this;
function insideOnly(){
alert(myOwner.name);
}
}//首先在構造函數中定義一個myOwner變量,將this關鍵字賦給它,之後就可以在私有函數裡使用這個變量來訪問對象本身了。
8、 特權方法私有成員不能在對象的外部訪問,不能訪問的對象有什麼用?我們可以使用特權方法來訪問這些私有屬性。所謂特權方法就是使用this關鍵字定義的函數,例如:
function Person(nameArg,genderArg,yearOfBirthArg,siteArg,privacyArg){
……
this.showPrivacy = function(){
var str = '秘密:' + this.name + privacy + '!';
alert(str);
};
}
var nahao = new Person('Top css',male,1989,'www.javava.org','有10跟腳趾頭');
nahao.showPrivacy();
我們首先給Person構造函數添加了一個showPrivacy特權方法,方法中使用了私有變量privacy的值。最後我們在nahao對象上調用該方法,結果如下:
9、 prototype淺析首先,我們要否定上面這句話“對Person.prototype的修改同樣會影響到使用Person定義的對象。”請看如下代碼:
Person.prototype = {
mark:'Person.Proto'
}
var nahao = new Person('Top css',male,1989,'www.javava.org');
Person.prototype = {
mark:'Person.NewProto'
}
alert(nahao.mark);
alert的輸出會是什麼呢?根據上面的經驗,在alert之前,對Person.prototype的最後修改將它的mark屬性賦值為'Person.NewProto'。但是實際的輸出結果:Person.Proto
這不是bug,而且各個浏覽器裡都一樣。原因分析如下:
Person.prototype = {
mark:'Person.Proto'
}
一段首先創建一個對象字面量,並且賦值給Person.prototype,我們稱這個對象字面量為Proto。
var nahao = new Person('Top css',male,1989,'www.javava.org');
在創建nahao對象並且按照構造函數初始化對象的同時,會悄悄給nahao對象設置一個內部屬性,我們暫且將其命名為xxx,並且將其賦值為Person.prototype的值,也就是上面提到的對象字面量Proto,JavaScript的動態繼承也就是由這個xxx實現的。(這個JavaScript的內部實現機制不是我拍腦門想出來的,是Netscape的工作人員的一篇文章裡提到的,下面也會用程序來證明這個流程。)然後,
Person.prototype = {
mark:'Person.NewProto'
}
這裡我們將創建另外一個對象字面量NewProto,並且賦值給Person.prototype。到這裡就很明顯了,盡管我們修改了 Person.prototype,但是並沒有影響到nahao對象。當我們訪問nahao.mark的時候,它首先在自己內部找,找不到就會去找xxx,自然就找到了Proto,而非NewProto。那麼xxx這個實現動態繼承的關鍵究竟是什麼呢?在FireFox中它是__proto__,有以下代碼為證。至於在IE中xxx是什麼我還沒找到。
Person.prototype = {
mark:'Person.Proto'
}
var nahao = new Person('Topcss','male',1989,'www.nahao8.com');
nahao.prototype = {
mark:'Person.NewProto'
}
alert(nahao.mark);
alert(nahao.__proto__.mark);//兩次alert的結果都是一樣的,都是Proto。
alert(nahao.__proto__===Person.prototype);//結構為true。
以上代碼經過測試適用於FireFox和chrome。NetScape應該也可以,IE不行。
個人觀點:Person.prototype = {}的方式最好只在定義構造函數的時候使用一次,而且要緊跟著構造函數寫,以後修改prototype的時候都使用Person.prototype.protertyA = ‘valueA’的形式。
10、 最後的構造函數我們在上面看到了定義對象,以及設這和修改其屬性的各種方法,我們可以在構造函數中定義屬性,可以在對象外部定義(靜態)屬性,也可以在對象的prototype中定義屬性。下面是我使用的大致格式:
function Person(nameArg,genderArg,yearOfBirthArg,siteArg,privacyArg){
//公有屬性
this.name = nameArg;
this.gender = genderArg;
this.yearOfBirth = yearOfBirthArg;
this.site = siteArg;
//私有屬性
var privacy = privacyArg;
//特權方法
this.showPrivacy = function(){
};
}
Person.prototype = {
//公有方法
info : function(){
},
func:function(){
}
}