每個Web開發者應該深諳的JavaScript規則(轉載)
alex此舉是為了給自己即將出版的新書做個預告,但短短幾句總結性的稱述提煉出了JavaScript的核心設計概念及編程思想,不可謂不精粹。當我看到這幾句話時,暗下思考,再查查犀牛書,才知道自詡精通js的我其實尚是一知半解。以下便來談談我對這幾句話的重新認識:
- JavaScript里一切皆是對象,包括函數。(Everything in JavaScript is an Object. Even functions)
我原來以為JavaScript 既然名為 (Java)Script,自然也是繼承Java語言的設計————在Java中,數據類型分為基本數據類型(number,boolean,char等)和對象數據類型————而其實JavaScript所操作的數據類型都是對象,類似于Ruby。怎么理解呢? 例如,整型和布爾值在Java代碼中是一個基本數據類型,它是沒有方法和屬性的,在JavaScript中是怎樣呢? 看如下的代碼:
//畫蛇添足的方法,僅作為example Number.prototype.abs = function() { returnMath.abs(this); } alert((-100).abs()); // 彈出返回值 100 Boolean.prototype.reverse = function() { return !this; } alert(true.reverse()); // 彈出返回值 false
alex更強調在JavaScript中函數也是對象,這是動態腳本語言的重要特性(作為對比,在Java中函數(方法)只是一種語法)。函數成為一個對象,所以函數完全可以看作數據:賦給變量、設為對象的屬性、甚至作為其他函數的參數。函數是對象帶來了巨大的靈活性,也是JavaScript面向對象編程的設計核心之一。當然與之而來的復雜性,也讓JavaScript倍受誤解。
- 所有對象都是可變的。(Every object is always mutable )
- "." 操作符等同于"[]"操作符。(The dot operator is equivalent to de-referencing by hash (e.g., foo.bar === foo["bar"]) )
- new 關鍵字實際上是先創建一個對象,再讓構造器方法在該對象域中執行。The new keyword creates an object that class constructors run inside of, thereby imprinting them
function Dog(name) { this.name = name; } var dog = new Dog("小明");
我以我的理解模擬 new 操作符的執行步驟:
var dog = newObject(); //首先創建一個新的Object對象 dog.prototype = Dog.prototype; // 設置構造器函數的原型對象為 dog 的原型對象 Dog.apply(dog, argumens); //將新對象傳遞給構造函數,此時構造函數可以用this來初始化新對象
所以 javascript 并非象java/C++的構造器函數那樣,先執行然后返回一個對象。而是先創建一個未定義屬性的干凈的Object對象,接著把構造器函數的原型對象設置為新對象的原型對象(構造器函數的原型對象是JavaScript自動為每個函數創建的)。最后再把這個對象交給構造器函數,在構造器函數中設置該對象其他的屬性和方法等等。
通過這樣的方式帶來的巨大動態特性就是, 可以象操作普通函數一樣操作構造器函數。__所有自定義的對象甚至可以使用同一個構造器函數__ 。實際上這也是Prototype和Dojo的核心設計思想。通過這樣的方式和原型對象的設計,JavaScript實現了與Java完全不同的面向對象設計。
- 所有函數都是閉句。(Functions are always closures (combine w/ previous rule to create OOP) )
閉包是一個把函數定義和作用域聯合在一起的對象...執行函數時使用的是在定義它們時就有效的作用域鏈,而不是在執行它們時才有效的作用域鏈...實際上所有函數都是閉包實現的…
順從這樣的理解:任何函數都有作用域,客戶端編程中頂層的全局域函數也是有作用域的,那就是window對象,所以全局函數也就是全局域和函數定義組合的閉包。
Alex說此句是JavaScript面向對象編程的重要規則,我就還不能完全參透了。暫時的理解就是如下代碼所示:
function Dog(name) { var name = name; function getName() { return name; } this.getName = getName; } var dog = new Dog("小明"); alert(dog.name); // 彈出"undefined" alert(dog.getName()); // 彈出"小明"
- this關鍵字關聯于執行時的作用域,而非定義時的作用域。(The this keyword is relative to the execution context, not the declaration context )
- 原型對象的屬性也是可變的(The prototype property is mutable )
我要感謝這篇短文,它促使我又認真的讀了一遍犀牛書的相關章節,同時也有了新的認識和心得。感受正如alex最后所說:
If all of that makes sense to you, JavaScript can be a fun, liberating experience. If not, it’s going to be a world of pain and broken expectations as you shed the baggage of less dynamic languages.
posted on 2006-07-09 17:58 小熊泡泡 閱讀(210) 評論(0) 編輯 收藏 所屬分類: Javascript