js是一門很強大的語言,靈活,方便。 目前我接觸到的語言當中,從語法角度上講,只有 Ruby 比它更爽。html
不過我接觸的動態語言只有: js ruby python flash的as 簡單的幾門, 應該算是井底之蛙之見。java
js 語法成分簡單,沒有 ruby 語言複雜。因此有時候我以爲她更乾淨(Ruby Fans 不要***我哦,我也是很愛很愛很愛Ruby的)!python
Prototype.js 無疑是 js的漂亮之做,從它身上應該能夠學到一些東西。ajax
若是你用 js 在頁面僅僅能寫出 if, alert等簡單的驗證代碼,或者想多瞭解一下Js, 那麼此文可能對你有幫助。正則表達式
好了,開始吧。ruby
如今我忽然想起了 Thinking in java 中的 "一切皆是對像", 其實我以爲這句話 有點不適合 java 反卻是更適合 jsapp
1.怎樣構造(初始化)對象?ide
var Prototype = { 函數
Version: '1.5.0_rc1', this
ScriptFragment: '(?:)((\n|\r|.)*?)(?:<\/script>)',
emptyFunction: function() {},
K: function(x) {return x}
}
就這樣,初始化了一個對象(名字就叫 Prototype),以及對象的四個成員: Version, ScriptFragment, emptyFunction, K
咱們也來試試:
var bbs = {
name: 'JavaEye',
version: '2.0',
describe: "作最棒的軟件開發交流區",
sayHello: function() { alert("hello, i'm javaeye! ") }
}
因而你能夠這樣使用: bbs.name 或 bbs.sayHello()
看到嗎? sayHello 是一個方法哦,不要驚慌,"一切都是對象",因此它和 name 是同樣的,只不過初始化,或定義的語法不同。想起 js 中的正則表達式中的那兩個杆杆了嗎? 可愛吧!
方法是對象,因此它能夠被看成參數傳遞,或者做爲方法的返回值。
因此 Prototype 中有一個 Version 屬性,還有一個匹配 script 的正則式字符串, 一個空方法emptyFunction,還有一個方法 K, 它僅僅返回參數。
沒問題吧,繼續!
2. 構造函數?
先讓咱們寫段代碼吧(中學時,我語文極差(大學沒語文了),我想寫代碼讓大家明白我內心真實的想法):
var Person = function(name) { // 這裏 Person 是一個方法
this.name = name;
}
var bencode = new Persion("bencode"); // 這裏像Java吧!
alert(bencode.name);
先看結果:
從 alert(bencode.name); 能夠知道,bencode是對象, 而 name 就是 bencode 的屬性, 它被正確地初始化爲 "bencode"
因此 var bencode = new Persion("bencode"); 就是構造了一個新的對象,Person() 至關於構造函數
因此 new 這個關鍵字, 就是構造一個新的對象,而且在這個對象上調用相應的方法,並將這個對象返回。
按上面說: 方法 若是用在 在 new 後面,就至關於成了構造函數了。
話又說回來了, 若是 var bencode = new Persion("bencode") 是 構造了一個對象,像Java, 那麼 Person 是否是類呢?
但是 Person 不是方法嗎? 但是方法不也是對象嗎? 類也是對象?
一切皆對象?
原本無一物!
好了,看 Prototype.js吧
var Class = {
create: function() {
returnfunction() {
this.initialize.apply(this, arguments);
}
}
}
初始化一個 Class 對象, 它有一個成員,是一個方法, 這個方法返因另外一個方法(方法是對象,因此能夠做爲參數或者返回值)
因此若是咱們這麼作:
var A = Class.create(); // 此時 A 是一個方法,方法體,下面解釋
var a = new A(...); // 對方法使用 new 操做符,就是構造一個新的對象,而後在這個對象上調用這個方法( 如今是 A)
上面分析說? A至關於類, 哈哈 Class.create(); // 終於名副其實
var a = new A(...); // 也是至關地直觀, 就是構造一個新的對象,類型 是A
new 操做符構造了對象,並調用了 方法, 這個方法到底作了什麼呢? 也就是上面沒有分析的東東,看看先:
var Class = {
create: function() {
returnfunction() { // 見[1]
this.initialize.apply(this, arguments); // 見[2]
}
}
}
[1]. new 操做符,就會在新產生的對象上調用這個方法
[2]. 哦? 這裏就是調用 this 對象上的 initialize方法, 並傳遞 arguments
換句話說,就是把構造的任務委託給 initialize 方法
initialize? 哪裏來? 見下面,類的擴展(繼承)
3. Prototype?
看段老代碼:
var Person = function(name) {
this.name = name;
}
var bencode = new Person("bencode");
bencode不是一個自閉的人,他應該能夠向javaeye介紹一下本身。
像這樣:
bencode.sayHello();
假如不能實現以上功能的話, 上面的 new,上面全部的東東都等於垃圾。
因此。須要給 Person 類加"實例方法"
題外話: 靜態方法如何添加? 看上面的 Class.create, 僅僅是一個對象的成員而已
好, 再來一段 (爲了完整性,上面的幾句話,再抄一次)
var Person = function(name) {
this.name = name;
}
Person.prototype = { // protype 是啥?
sayHello: function() {
alert("hi, javaeye, I'm " + this.name);
}
}
var bencode = new Person("bencode");
bencode.sayHello();
運行代碼,經過!
prototype是啥? 請暫時忘記 Prototype(prototype.js) 這個庫,名字同樣而已!
讓咱們再從結果上去分析(第一次咱們用這種方法分析而得出了 new 的做用),
咱們在思考:
要想 bencode.sayHello() 正常運行
bencode 是一個對象, 這是咱們已經知道的
sayHello() 應該是 bencode 這個對象的方法才能夠
但是bencode 這個對象是 new 操做符產生的, 而 new 此時做用於 Person 這個 "類"
那麼, 哦? 那麼有兩種可能:
1. new 產生的那個新對象是否是就是 Person.prototype
2. Person.prototype 中的成員 將會被 new 操做符添加到 新產生的對象中
再看:
Person.prototype = {
sayHello: function() {
alert("hi, javaeye, I'm " + this.name); // 這裏有this
}
}
this.name, 這裏的 this 指什麼?因此第一個可能講不通呀
回憶起這段:
var Person = function(name) {
this.name = name;
}
若是這裏的 this 表明着新產生的對象的話。
那麼第二種狀況就講得通了, new 將會把 Person.prototype 這個對象的成員放到 這個新對象中。 與當前行爲相符。
因此: Person 的 Prototype 對象中的 成員, 將會被添加到 新產生的對象 中(我是這樣理解的)
(不知道 Js解釋器是否是開源的, 有空我得去看看,怎麼實現的。)
嘿,默認的 Prototype 就是 Object 哦!
4. 擴展?繼承?
什麼是擴展?啥是繼承? ! 我從爸爸那獲得了什麼?
想不通!
仍是實際點:
有一個類A, 它有一個 sayHello方法
var A = function() {
}
A.prototype = {
sayHello: function() {
alert("sayHello A")
}
}
我想構造一個 B 類,讓他繼承 A 對象, 這句話太抽象。
其實咱們可能想這樣:
var b = new B();
b.sayHello(); // 調用 A 的 sayHello
這應該是繼承的第一層含義(重用)
怎麼辦到呢?
var B = function() { // 這裏是有一個B類了
}
怎麼樣添加"實例方法"? 快點想起 Prototype!!!
B.prototype = A.prototype
這樣行了嗎? 恭喜, 運行經過!
讓咱們整合一次
var A = function() {
}
A.prototype = {
sayHello: function() {
alert("sayHello A");
}
}
var B = function() {
}
B.prototype = A.prototype;
var b = new B();
b.sayHello();
但是若是 B 是這樣呢?
var B = function() {
}
B.prototype = {
sayHi: function() {
alert("sayHi B");
}
}
咱們是否是應該將 A.prototype 中的內容添加到 B.prototype 對象中,而不是代替它呢? 固然。
這樣才能"擴展"
題外話?多態在哪裏? 嘿嘿
好了,足夠多了, 那prototype.js 是怎麼樣"擴展"的呢?
Object.extend = function(destination, source) {
for (var property in source) {
destination[property] = source[property];
}
return destination;
}
這個只是簡單地把 source 的成員, 添加到 destination 對象中嘛, 哪裏看得出擴展?
若是我這樣呢?
var A = function() {
}
A.prototype = {
sayHello: function() {
alert("sayHello A")
}
}
var B = function() {
}
Object.extend(B.prototype, A.prototype); // 先添加父類(A)成員
Object.extend(B.prototype, { // 再添加B類成員, 若是是同名,則覆蓋,行爲符合 "多態"
sayHi: function() {
alert("sayHi B");
}
});
回憶剛纔的 Class.create():
var Person = Class.create();
var bencode = new Person("bencode");
剛纔說過, 調用 new 時, 將會建立一個新對象,而且調用 Person 方法, Person 方法會委託給 "新產生對象"的 initialize方法
怎麼樣給新產生對象添加 initialize 方法? 哈哈,輕鬆
Object.extend(Person.prototype, {
initialize: function() {
this.name = name;
} //,
// 下面能夠添加其餘實例方法。
});
因此, 咱們使用 Prototype 建立類通常格式是這樣的:
var ClassName = Class.create();
Object.extend(ClassName.prototype, {
initialize: function(...) { // 這就至關於構造函數
}
//...
});
若是咱們要繼承一個類,只要:
var ClassName = Class.create();
Object.extend(ClassName.prototype, SuperClassName.prototype);
Object.extend(ClassName.prototype, {
initialize: function(...) {
}
//...
});
面向對象部分基本上就這樣。
但願對你們有點幫助!
原本想再接着寫 Prototype.js 的源碼解讀,但一來是由於時間,第二是發現也沒有這個必要。
這種東西是看起來快,寫起來慢的。哈哈!
原文網址