JavaScript var是用來定義一個變量,this常用來定義或調用一個屬性或方法。但是在全局范圍內,this和var定義變量是等價的。
window
console.log('window:', name); var name = 'stone'; this.name = 'niqiu'; console.log('var:',name); console.log('this:',this.name);
window對象有name屬性,初始值為空,但第一個console的時候怎么獲取值了呢。 發現這個window記錄的是上次的值。重新打開頁面,只執行 console.log('window:', name); 輸出為空。
console.log('window:', name); var name = 'stone';
刷新兩次后輸出stone. 所以window對象在刷新的時候並沒有重新創建。window是的{}對象。沒有構造函數,不能new。
function與{}
在函數內部,var定義的是局部變量,而this定義的是屬性。這兩者沒有覆蓋。但新創建的對象是無法獲取到局部變量的。
var Fool = function () { var name = 'stone'; var nikename = 'stoneniqiu'; this.name = 'niqiu'; this.getName = function () { console.log('var', name); console.log('this', this.name); }; this.getNickname = function() { return nikename; }; };
console.log(f.name); //niqiu console.log(f.nikename);//undefined console.log(f.getNickname());//stoneniqiu
但是如果使用{}定義對象,內部變量等於全部都是屬性。
var block = { name: 'stone', nickname:'stoneniqiu', getName: function () { // return this.name;//stone return name; //'windows name'; }, getNickname:function() { return this.nickname; }, printAllName:function() { console.log(this.getNickname()); console.log(this.getName()); } }; console.log(block.name);//stone console.log(block.getName()); //windows name
像window對象一樣,{}創建的對象不能new,因為沒有構造函數。
所以如果對象復用,比較大,還是用function的形式比較好,分開私有變量和公共屬性或方法,function的內部模塊可以用{}的形式。
通過this可取得它們所屬的上下文的方法稱為公共方法。this到對象的綁定發生在調用的時候,這個“超級”延遲綁定使得函數可以對this高度復用。
this指的是當前執行的對象,為避免this發生變化。常用一個變量暫存一下this。
var self=this
神奇的回調
下面看個例子,對象的參數中定義了回調方法,但我們傳入Fool自身的一個方法,居然執行了。
var Fool = function (config) { var parmas = { callback: function() { console.log('raw callback'); } }; parmas = $.extend(parmas, config); var name = 'stone'; var nikename = 'stoneniqiu'; this.name = 'niqiu'; this.getName = function () { console.log('var', name); console.log('this', this.name); }; this.getNickname = function () { return nikename; }; this.doSomething = function () { parmas.callback(); }; }; var f = new Fool({callback:function() { $("#bt").click(function() { f.getName() }); }}); f.doSomething();
運行無誤,點擊button 觸發getName方法。但如果直接下面這樣寫,就會報錯了,這錯的很符合常理。
var f = new Fool({callback:f.getName()});
再修改下,用匿名函數包起來,也能跑。
var f = new Fool({callback:function() { (function() { f.getName(); })(); }}); f.doSomething();
今天弄明白,這其實是一個閉包問題,函數內部執行的f.getName()相當於是一個變量,它綁定外部的f,而並不是函數構建那一刻的f,所以在匿名函數構建時不會在意f是否創建了。相當於下面的這個經典問題:
var addhandle=function(node){ var i for(i=0;i<node.length;i++){ node[i].onclick=function(e){ alert(i); } } }
如果執行上面的方法,綁定的就是循環結束之后的i。而不是循環那一刻的i。上面循環中的代碼如果修改成下面這樣。
nodes[i].onclick=function(i){ return function(e){ alert(e) } }(i)
就是函數構建時的變量i了。