一、JavaScript的誕生
1994年遂铡,網(wǎng)景公司(Netscape)發(fā)布了Navigator瀏覽器0.9版入问。這是歷史上第一個比較成熟的網(wǎng)絡(luò)瀏覽器
特點:只能用來瀏覽,不具備與訪問者互動的能力班套,一切都需要服務(wù)器端進行判斷
需求:需要一種網(wǎng)頁腳本語言,使得瀏覽器可以與網(wǎng)頁互動
時代:1.1994年正是面向?qū)ο缶幊套钆d盛的時期故河,Brendan Eich受到影響吱韭,使JavaScript里面所有的數(shù)據(jù)類型都是對象,同時他考慮是否要設(shè)計“繼承”機制
2.1995年Sun公司將Oak語言改名為Java鱼的,正式向市場推出理盆,并大肆宣傳痘煤,看上去很可能成為未來的主宰;網(wǎng)景公司動心猿规,決定與Sun公司結(jié)盟衷快,當時的形勢就是,網(wǎng)景公司的整個管理層坎拐,都是Java語言的信徒烦磁,Sun公司完全介入網(wǎng)頁腳本語言的決策。因此哼勇,Javascript后來就是網(wǎng)景和Sun兩家公司一起攜手推向市場的都伪,這種語言被命名為"Java+script"并不是偶然的。
3.1995年5月积担,網(wǎng)景公司做出決策陨晶,未來的網(wǎng)頁腳本語言必須"看上去與Java足夠相似",但是比Java簡單帝璧,使得非專業(yè)的網(wǎng)頁作者也能很快上手先誉。Brendan Eich被指定為這種"簡化版Java語言"的設(shè)計師。
二的烁、Brendan Eich的選擇
考慮到JavaScript里面都是對象褐耳,必須有一種機制,將所有對象聯(lián)系起來渴庆,所以铃芦,他最后還是設(shè)計了“繼承”。
為了減少初學(xué)者入門難讀襟雷,他并未引入“類”的概念刃滓。
考慮到C++和Java語言都是用new命令,生成實例耸弄,于是他就把new命令引入了JavaScript咧虎,用來從原型對象生成一個實例對象。
ClassName *object = new ClassName(param);
// C++
Foo foo = new Foo();
// Java
但是计呈,JavaScript并沒有“類”砰诵,如何表示原型對象呢?
此時捌显,他想到C++和Java使用new命令時茁彭,都會調(diào)用“類”的構(gòu)造函數(shù),因此他做了一個簡化的設(shè)計苇瓣,在JavaScript語言中,new命令后面跟的不是類偿乖,而是構(gòu)造函數(shù)击罪。
function DOG(name) { // DOG構(gòu)造函數(shù)哲嘲,表示狗對象的原型
this.name = name;
}
var dogA = new DOG('大毛'); // new 構(gòu)造函數(shù),生成一個狗對象的實例
alert(dogA.name); // 大毛
三媳禁、new運算符的缺點
用構(gòu)造函數(shù)生成實例對象眠副,有一個缺點:無法共享屬性和方法。
function DOG(name) {
this.name = name; this.species = '犬科';
}
var dogA = new DOG('大毛');
var dogB = new DOG('二毛');
dogA.species = '貓科';
alert(dogB.species); // 犬科
我們在DOG對象的構(gòu)造函數(shù)中設(shè)置了共有屬性species竣稽,當修改實例對象中的一個囱怕,另一個并不會受到影響,每一個實例對象都有著自己的屬性和方法的副本毫别。
這樣就無法做到數(shù)據(jù)共享娃弓,造成了資源的浪費。
?構(gòu)造函數(shù)中的this代表了新創(chuàng)建的實例對象
四岛宦、prototype屬性的引入
因此台丛,Brendan Eich決定為構(gòu)造函數(shù)設(shè)置一個prototype屬性。
這個屬性包含一個對象砾肺,所有實例對象需要共享的屬性和方法挽霉,都放在這個對象里面,而不需要共享的屬性和方法变汪,就放在構(gòu)造函數(shù)里面侠坎。
實例對象一旦創(chuàng)建,將自動引用prototype對象的屬性和方法裙盾,即实胸,實例對象的屬性和方法分為兩種:本地+引用
function DOG(name) {
this.name = name;
}
DOG.prototype = { species:'犬科' };
var dogA = new DOG('大毛');
var dogB = new DOG('二毛');
alert(dogA.species); // 犬科
alert(dogB.species); // 犬科
DOG.prototype.species = '貓科';
alert(dogA.species); // 貓科
alert(dogB.species); // 貓科
兩個實例對象共享prototype對象中的屬性,只要修改了prototype對象闷煤,就會同時影響到兩個實例對象童芹。
由于所有的實例對象共享同一個prototype對象,則prototype對象就好像是實例對象的原型鲤拿,而實例對象則好像是“繼承”了prototype對象一樣假褪。
五、JavaScript的10個設(shè)計缺陷
-前言:為什么有設(shè)計缺陷近顷?
1.設(shè)計階段過于倉促(僅僅10天生音,設(shè)計師僅為了交差,本人并不愿意這樣設(shè)計窒升;且設(shè)計初衷就是為了解決一些簡單的網(wǎng)頁互動缀遍,并沒有考慮復(fù)雜應(yīng)用的需要)
2.沒有先例可以參考(JavaScript同時結(jié)合了函數(shù)式編程和面向?qū)ο缶幊痰奶攸c,這可能是歷史上的第一例饱须,直至目前域醇,JavaScript仍是世界上唯一使用prototype繼承模型的主要語言)
3.過早的標準化(JavaScript退出一年半之后,國際標準就問世了。設(shè)計缺陷還沒有充分暴露就成了標準)
-10個設(shè)計缺陷
1.不適合開發(fā)大型程序
JavaScript咩有名稱空間譬挚,很難模塊化锅铅??减宣?
沒有如何將代碼分布在多個文件的規(guī)范
允許同名函數(shù)的重復(fù)定義盐须,后面的定義可以覆蓋前面的定義,很不利于模塊化加載
2.非常小的標準庫
標準函數(shù)庫非常小漆腌,只能完成一些基本操作贼邓,很多功能并不具備
3.null和undefined
null屬于對象的一種,意思為該對象為空闷尿;
undefined是一種數(shù)據(jù)類型塑径,表示未定義;
typeof null; // object
typeof undefined; //undefined
var foo;
foo == null ; // true
foo == undefined; // true
foo === null; // false
foo === undefined; // true
4.全局變量難以控制
JavaScript的全局變量悠砚,在所有模塊中都是可見的晓勇;
任何一個函數(shù)內(nèi)部都可以生成全局變量,這大大加劇了程序的復(fù)雜性灌旧;
5.自動插入行尾分號
JavaScript的所有語句绑咱,都必須以分號結(jié)尾,但是如果忘記加枢泰,編譯器也不會報錯描融,而是自動為你加上,這使得一些錯誤很難發(fā)現(xiàn)
6.加號運算符
+有兩個含義
數(shù)字與數(shù)字的和 1+1 // 2
字符與字符的連接 "1"+"10" // 110 1+"10" // 110
7.NaN
NaN是一種數(shù)字衡蚂,表示超出了解釋器的極限窿克,有一些奇怪的特性
NaN === NaN; // false
NaN !== NaN; // true
console.log(1+NaN); // NaN
8.數(shù)字和對象的區(qū)分
由于JavaScript的數(shù)組也屬于對象,所以要區(qū)分一個對象到底是不是數(shù)組毛甲,相當麻煩
if ( arr && typeof arr === 'object' && typeof arr.length === 'number' && !arr.propertyIsEnumerable('length')){
alert("arr is an array");
}
9.==和===年叮、
==用來判斷兩個值是否相等,當兩個值的類型不同時玻募,會發(fā)生自動轉(zhuǎn)換
=== 需要兩個值和類型都相同
10.基本類型的包裝對象
JavaScript有三種基本數(shù)據(jù)類型:字符串只损、數(shù)字和布爾值;他們都有相應(yīng)的構(gòu)建函數(shù)七咧,可以生成字符串對象跃惫、數(shù)字對象和布爾值對象
new Boolean(false);
new Number(1234);
new String("Hello World");
alert( typeof 1234); // number
alert( typeof new Number(1234)); // object
參考
1.Javascript繼承機制的設(shè)計思想---阮一峰
3.Javascript的10個設(shè)計缺陷---阮一峰
4.《JavaScript高級程序設(shè)計》(第四版)