JavaScript讀書筆記

[b]一. javascript基礎[/b]
1. 使用同一個var語句定義的變量不必有相同的類型

var test="hi", age=25


2. 在使用變量之前不必聲明,javascript的解釋程序遇到未聲明的標示符時,用該變量名創建一個全局變量,並將其初始化爲指定的值。

var test = "hi"
test1 = test + "world"


3. javascript中的變量可以存放兩種類型的值
a. 原始值,它們的值直接存儲在變量訪問的位置。一共有5種:Undefined, Null, Boolean, Number, String。
b. 引用值,存儲在變量處的值是一個指針,指向存儲對象的內存處。

4. Undefined類型
a. 當聲明的變量未被初始化時,該變量的默認值是undefined。
b. 當函數無明確返回值時,返回的值也是undefined。

5. Null類型
undefined是從null派生出來的,所以null==undefined,但是它們的含義不同。undefined是聲明瞭變量但未對其初始化時賦予該變量的值,null則用於表示尚未存在的對象。

var i;
alert(i == undefined); //true
alert(i == null); //true
alert(undefined == null); //true


6. toString方法
所有對象都有toString方法,可以用來轉化自身的值爲字符串。

7. parseInt方法
a. 該方法會轉化字符串的部分值

var i1 = parseInt("blue"); //NaN
var i2 = parseInt("123blue"); //123

b. 如果十進制數包含前導0,則要使用基數10,否則有可能會以外得到八進制的值。

var i1 = parseInt("010"); //8
var i2 = parseInt("010", 8); //8
var i3 = parseInt("010", 10); //10


8. Number方法
該方法和parseInt不同,它會試着轉化整個值

var i1 = Number("blue") //NaN
var i1 = Number("123blue") //NaN


9. typeof和instanceof
這兩個運算符都用於指示變量的類型,但是typeof只返回5種值:undefined,boolean,number,string,object,其中若變量是引用類型或Null類型,則都返回object。這個時候要判斷具體的類型就需要instanceof運算符了。

var o = new String("sss");
alert(typeof o); //object
alert(o instanceof String); //true

alert(typeof null); //object

var s = "sss";
alert(typeof s); //string
alert(s instanceof String); //false

//注意沒有string類型,以下寫法是錯誤的。
//alert(s instanceof string);


10. Object類
1. javascript中的所有類都由這個類繼承而來。這個類有以下兩個屬性:
Constructor:對創建對象的函數的引用。
Prototype:對該對象的對象原型的引用。

11. Function類
Function類創建函數的語法如下:
var f = new Function(a1, a2, ... , an, function_body);
a1~an都是參數,最後一個是函數主體。
在ECMAScript中,函數名只是指向函數對象的引用值,行爲就像其他指針一樣。

function f1(v){
alert(v);
}
//以上函數用Function類重寫
var f1 = new Function("v", "alert(v)");


[b]二. 對象基礎[/b]
1. 聲明和實例化
對象是用關鍵字new後跟要實例化的類的名字創建的

var o = new Object();
var s = new String();


2. 關鍵字this
a. 在構造方法中,this指向的是被new創建的對象。
b. 在普通方法中,this指向的是該方法所屬的對象。

3. 定義類或對象
a. 工廠方式:因爲“晚綁定”,對象的屬性可以在對象創建後動態定義,所以可以這樣:

function createCar(color, doors){
var tempCar = new Object();
tempCar.color = color;
tempCar.doors = doors;
tempCar.showColor = function(){
alert(this.color);
}
}

var car1 = createCar("red", 4);
var car2 = createCar("blue", 2);

b. 構造函數方式:使用new和this,在構造函數內部不創建對象,在外部調用new的時候,在執行構造函數的第一行前先創建一個對象,只有用this才能訪問:

function Car(color, doors){
this.color = color;
this.doors = doors;
this.showColor = function(){
alert(this.color);
}
}

var car1 = new Car("red", 4);
var car2 = new Car("blue", 2);

c. 混合構造函數/原型方式
以上兩種方式都有個問題,就是每次創建對象都會創建對象的方法,雖然可以把方法定義在構造函數外面,然後通過屬性指向該方法,但是這種做法看起來不像對象的方法。所以還有一種構造函數使用原型方式來實現,但是純原型方法又帶來另外兩個問題,1.無法在構造函數中指定參數;2.對於屬性指向對象的情況會產生問題,因爲對象是不能被多個實例共享的。由此出現了混合構造函數/原型方式,用構造函數定義對象的所有非函數屬性,用原型方式定義對象的函數:

function Car(color, doors){
this.color = color;
this.doors = doors;
this.drivers = new Array("smy", "zq");
}
Car.prototype.showColor = function(){
alert(this.showColor);
}

var car1 = new Car("red", 4);
var car2 = new Car("blue", 2);


4. 修改對象
可以用prototype屬性爲任何已有的類添加新方法或修改已有的方法。

Car.prototype.showColor = function(){
alert("this car's color is " + this.color);
}


5. 刪除對象屬性
可以使用delete是用來刪除對象的某個屬性

delete Car.color;


[b]三. 繼承[/b]
1. 對象冒充
在使用構造函數來創建對象的過程中,this指向的是被new創建的對象。而在普通的方法調用中this指向的是該方法所屬的對象,所以可以這樣使用this:

function ClassA(color){
this.color = color;
this.sayColor = function(){
alert(this.color);
}
}

function ClassB(color, doors){
this.newMethod = ClassA;
this.newMethod(color);
delete this.newMethod;

this.doors = doors;
this.sayDoors = function(){
alert(this.doors);
}
}

var o = new ClassB("red", 2);
o.sayColor();
o.sayDoors();

以上有幾點要注意:
1. 使用delete是爲了避免在ClassB構造方法外部調用ClassA方法。
2. this.newMethod(color);絕對不能使用ClassA(color)代替,只有在前者中this會指向new ClassB("red", 2);創建的對象,而後者中this指向的將是windows。

2. call()和apply()方法
跟對象冒充類似,call和apply都是用指定的對象代替調用函數中的this對象,它們之間的不同在於apply使用了數組表示傳遞給調用函數的參數。

//使用call
function ClassB(color, doors){
ClassA.call(this, color);

this.doors = doors;
this.sayDoors = function(){
alert(this.doors);
}
}
//使用apply
function ClassB(color, doors){
ClassA.apply(this, arguments);

this.doors = doors;
this.sayDoors = function(){
alert(this.doors);
}
}


3. 原型鏈
prototype是對象的模板,prototype對象的任何屬性和方法都被傳遞給那個類的所有實例。

function ClassA(){}

ClassA.prototype.color = "red";
ClassA.prototype.sayColor = function(){
alert(this.color);
}

function ClassB(){}

ClassB.prototype = new ClassA();
ClassB.prototype.doors = 4;
ClassB.prototype.sayDoors = function(){
alert(this.doors);
}

var o = new ClassB();
o.sayColor();
o.sayDoors();

原型鏈的本質是調用new ClassA()時創建一個ClassA對象,並把這個對象賦值給ClassB.prototype,這樣ClassB的所有對象都有了ClassA對象的屬性和方法。另外要注意的是子類的所有屬性和方法必須出現在prototype屬性被賦值之後,因爲在它之前賦值的所有方法都會被刪除。
使用這種方式構造的對象在調用instanceof運算符時,對ClassB的所有實例,對ClassA和ClassB對返回true;但是使用原型鏈方式構造的對象將帶來和使用原型方式創建對象時的相同的問題:1.無法在構造函數中指定參數;2.對於屬性指向對象的情況會產生問題,因爲對象是不能被多個實例共享的。另外原型鏈不支持多重繼承,因爲原型鏈會用另一類型的對象重寫prototype屬性。

4. 混合對象冒充/原型鏈方式
用對象冒充繼承構造函數的屬性,用原型鏈繼承prototype對象的方法。

function ClassA(color){
this.color = color;
}

ClassA.prototype.sayColor = function(){
alert(this.color);
}

function ClassB(color, doors){
ClassA.call(this, color);
this.doors = doors;
}

ClassB.prototype = new ClassA();
ClassB.prototype.sayDoors = function(){
alert(this.doors);
}

var o = new ClassB("red", 2);
o.sayColor();
o.sayDoors();

注意:執行以上的代碼,color這個屬性存在於ClassB.prototype中,而不存在於ClassA.prototype。可以試着在上述代碼中把ClassB.prototype = new ClassA();替換成ClassB.prototype = new ClassA("red");

alert(ClassA.prototype.color); //undefined
alert(ClassB.prototype.color); //red
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章