Javascript中的對象什麼是對象 我們可以把Javascript中對象理解為一組無序的索引值對,就好像C#中的Dictionary<string,Object>一樣。Key是屬性的名稱,而value可以為以下3種類型: 基本值(string, number, boolean, null, undefined)對象函數複製代碼var o = new Object();o["name"] = "jesse"; //基本值作為對象屬性o["location"] = { //對象作為對象屬性 "city": "Shanghai", "district":"minhang"}; // 函數 作為對象屬性o["sayHello"] = function () { alert("Hello, I am "+ this.name + " from " + this.location.city);} o.sayHello();複製代碼遍曆屬性 在C#中我們是可以用foreach對Dictionary<string,Object>進行遍曆的,如果說對象在Javascript中是一組索引值對的話,那我們如何進行遍曆呢? 複製代碼for (var p in o) { alert('name:'+ p + ' type:' + typeof o[p] );}// name:name type:string// name:location type:object// name:sayHello type:function複製代碼 上面的這種遍曆方式會把原型中的屬性也包括進來,關於什麼是原型,以及如何區分原型和執行個體中的屬性我們下面會講到。 建立對象 其實在上面我們已經建立了一個對象,並且使用了以下兩種建立對象的方式。 利用new建立一個Object的執行個體。字面量 我們上面的o是用第一種方式建立的,而o中的location屬性則是用字面量的方式建立的。而第一種方式其實也有一種名字叫做建構函式模式,因為Object實際上是一個建構函式,為我們產生了一個Object的執行個體。如果對於建構函式這一塊還有不清楚的話,趕緊去看我的第一篇 類型基礎Object與object吧。 除了以上兩種方式以外,我們一些建立對象的方式,我們也來一起看一下: 原廠模式複製代碼function createPerson(name, age, job){ var o = new Object(); o.name = name; o.age = age; o.job = job; o.sayName = function(){ alert(this.name); }; return o;}var person1 = createPerson('Jesse', 29, 'Software Engineer');var person2 = createPerson('Carol', 27, 'Designer');複製代碼 這種模式建立的對象有一個問題,那就是它在函數的內部為我建立了一個Object的執行個體,這個執行個體跟我們的建構函式createPerson是沒有任何關係的。 因為我在內部用new Object()來建立了這個對象,所以它是Object的執行個體。所以如果我們想知道它是具體哪個function的執行個體,那就不可能了。 建構函式模式 原廠模式沒有解決對象識別的問題,但是我們可以想一下,Object()實際上也是一個函數,只不過當我在它前面加上一個new的時候,它就變成了一個建構函式為我們產生一個Object的執行個體。那麼我同樣也可以在其它函數前面加上new這樣就可以產生這個函數的執行個體了,這就是所謂的建構函式模式。 複製代碼function Person(name, age, job){ this.name = name; this.age = age; this.job = job; this.sayName = function(){ alert(this.name); };} var p1 = new Person('Jesse', 18, 'coder');alert(p1 instanceof Person); // true複製代碼詳解this this在Javascript中也可以算是一個很神奇對象,沒錯this是一個對象。我們在上一篇範圍和範圍鏈中講到了變數對象,變數對象決定了在當前的執行環境中有哪些屬性和函數是可以被訪問到的,從某種程度上來說我們就可以把this看作是這個變數對象。我們之前提到了最大的執行環境是全域執行環境,而window就是全域執行環境中的變數對象,那麼我們在全域環境中this===window是會返回true的。 除了全域執行環境以外,我們還提到了另外一種執行環境,也就是函數。每一個函數都有一個this對象,但有時候他們所代表的值是不一樣的,主要是這個函數的調用者來決定的。我們來看一下以下幾種情境: 函數function f1(){ return this;} f1() === window; // global object 因為當前的函數在全域函數中運行,所以函數中的this對象指向了全域變數對象,也就是window。這種方式在strict 模式下會返回undefined。 對象方法複製代碼var o = { prop: 37, f: function() { return this.prop; }}; console.log(o.f()); // logs 37複製代碼 在對象方法中,this對象指向了當前這個執行個體對象。注意: 不管這個函數在哪裡什麼時候或者怎麼樣定義,只要它是一個對象執行個體的方法,那麼它的this都是指向這個對象執行個體的。 複製代碼var o = { prop: 37 };var prop = 15; function independent() { return this.prop;} o.f = independent;console.log(independent()); // logs 15console.log(o.f()); // logs 37複製代碼 區別:上面的函數independent如果直接執行,this是指向全域執行環境,那麼this.prop是指向我們的全域變數prop的。但是如果將independent設為對象o的一個屬性,那麼independent中的this就指向了這個執行個體,同理this.prop就變成了對象o的prop屬性。 建構函式 我們上面講到了用建構函式建立對象,其實是利用了this的這種特性。在建構函式中,this對象是指向這個建構函式執行個體化出來的對象。 複製代碼function Person(name, age, job) { this.name = name; this.age = age; this.job = job; this.sayName = function () { alert(this.name); };} var p1 = new Person('Jesse', 18, 'coder');var p2 = new Person('Carol',16,'designer');複製代碼 當我們執行個體化Person得到p1的時候,this指向p1。而當我們執行個體化Person得到p2的時候,this是指向p2的。 利用call和apply 當我們用call和apply去調用某一個函數的時候,這個函數中的this對象會被綁定到我們指定的對象上。而call和apply的主要區別就是apply要求傳入一個數組作為參數列表。 複製代碼function add(c, d) { return this.a + this.b + c + d;} var o = { a: 1, b: 3 }; // 第一個參數會被綁定成函數add的this對象add.call(o, 5, 7); // 1 + 3 + 5 + 7 = 16 // 第二個參數是數組作為arguments傳入方法addadd.apply(o, [10, 20]); // 1 + 3 + 10 + 20 = 34複製代碼在bind方法中 bind方法是 存在於function的原型中的 Function.prototype.bind,也就是說所有的function都會有這個方法。但我們調用某一個方法的bind的時候,會產生一個和原來那個方法一樣的新方法,只不過this是指向我們傳得bind的第一個參數。 複製代碼function f() { return this.a;} var g = f.bind({ a: "azerty" });console.log(g()); // azerty var o = { a: 37, f: f, g: g };console.log(o.f(), o.g()); // 37, azerty複製代碼在dom元素事件處理器中 在事件處理函數中,我們的this是指向觸發這個事件的dom元素的。 HTML代碼 複製代碼<html><body> <div id="mydiv" style="width:400px; height:400px; border:1px solid red;"></div> <script type="text/javascript" src="essence.js"></script></body></html>複製代碼JavaScript代碼 function click(e) { alert(this.nodeName);} var myDiv = document.getElementById("mydiv");myDiv.addEventListener('click', click, false); 當我們點擊頁面那個div的時候,毫無疑問,它是會顯示DIV的。