2013-01-19 29 views
8

我想了解jQuery類,但它不會很好。使用jQuery創建一個簡單的JavaScript類

我的目標是使用一類這個方法(或想了解一個更好的方式來做到這一點):

var player = new Player($("playerElement")); 
player.InitEvents(); 

用別人的例子,這是我的嘗試:

$.Player = function ($) { 

}; 

$.Player.prototype.InitEvents = function() { 

    $(this).keypress(function (e) { 
     var key = e.which; 
     if (key == 100) { 
      MoveRight(); 
     } 
     if (key == 97) { 
      MoveLeft(); 
     } 
    }); 
}; 

$.Player.prototype.MoveRight = function() { 
    $(this).css("right", this.playerX += 10); 
} 

$.Player.prototype.MoveLeft = function() { 
    $(this).css("right", this.playerX -= 10); 
} 

$.Player.defaultOptions = { 
    playerX: 0, 
    playerY: 0 
}; 

最終目標是使用鍵盤字母AD左右移動屏幕上的角色。

我有一種感覺,我正在做一些非常錯誤的事情,這個「班級」 ,但我不知道爲什麼。

(對不起我的英語)

+0

'this'實例方法內引用實例對象本身,所以你不能使用'$(this).keypress','$(this).css'等,因爲'this'不引用DOM元素和查詢字符串。你的函數調用也是錯誤的,它應該讀取'this。MoveRight()'但是當你處在一個將'this' context設置爲DOM元素本身的jQuery處理程序中時,您需要將實例的'this'賦值給作用域鏈中一個級別的變量,以便您可以在處理程序中訪問它來調用它的'MoveRight' /'MoveLeft'方法。 –

+0

你能告訴我你將如何改變我的代碼來解決我所做的問題嗎?如果我可以編寫一個好的代碼與我的代碼相比,我會更容易看到我做了什麼。 (如果不是太難) – samy

+0

我可以嘗試男人,但它比「修復」更接近完全重寫。 ':P'我會看看我能否舉一個簡單的例子。 –

回答

19

一個重要的問題是,你必須要傳遞的jQuery對象/元素分配給this.element - 或其他this.propertyName - 讓你可以稍後在實例的方法中訪問它。

您也不能直接調用MoveRight()/MoveLeft(),因爲這些函數沒有在作用域鏈中定義,而是在實例構造函數的原型中定義,因此您需要引用實例本身來調用這些函數。

更新和評論如下代碼:

(function ($) { //an IIFE so safely alias jQuery to $ 
    $.Player = function (element) { //renamed arg for readability 

     //stores the passed element as a property of the created instance. 
     //This way we can access it later 
     this.element = (element instanceof $) ? element : $(element); 
     //instanceof is an extremely simple method to handle passed jQuery objects, 
     //DOM elements and selector strings. 
     //This one doesn't check if the passed element is valid 
     //nor if a passed selector string matches any elements. 
    }; 

    //assigning an object literal to the prototype is a shorter syntax 
    //than assigning one property at a time 
    $.Player.prototype = { 
     InitEvents: function() { 
      //`this` references the instance object inside of an instace's method, 
      //however `this` is set to reference a DOM element inside jQuery event 
      //handler functions' scope. So we take advantage of JS's lexical scope 
      //and assign the `this` reference to another variable that we can access 
      //inside the jQuery handlers 
      var that = this; 
      //I'm using `document` instead of `this` so it will catch arrow keys 
      //on the whole document and not just when the element is focused. 
      //Also, Firefox doesn't fire the keypress event for non-printable 
      //characters so we use a keydown handler 
      $(document).keydown(function (e) { 
       var key = e.which; 
       if (key == 39) { 
        that.moveRight(); 
       } else if (key == 37) { 
        that.moveLeft(); 
       } 
      }); 

      this.element.css({ 
       //either absolute or relative position is necessary 
       //for the `left` property to have effect 
       position: 'absolute', 
       left: $.Player.defaultOptions.playerX 
      }); 
     }, 
     //renamed your method to start with lowercase, convention is to use 
     //Capitalized names for instanceables only 
     moveRight: function() { 
      this.element.css("left", '+=' + 10); 
     }, 
     moveLeft: function() { 
      this.element.css("left", '-=' + 10); 
     } 
    }; 


    $.Player.defaultOptions = { 
     playerX: 0, 
     playerY: 0 
    }; 

}(jQuery)); 

//so you can use it as: 
var player = new $.Player($("#playerElement")); 
player.InitEvents(); 

Fiddle

還要注意的是JavaScript並沒有實際的「類」(至少直到ES6得到實施)也沒有方法(其定義是相關聯專門用於類),而是提供類似類的甜語法的構造函數。下面是關於JS的「假」的方法由TJ克羅德寫的真棒文章,這是一個有點先進的,但每個人都應該能學到新的東西從閱讀它:
http://blog.niftysnippets.org/2008/03/mythical-methods.html

2

當您使用this裏面你Player原型功能,this指向當前的Player對象。

但是,當您使用$(this).keypress它要求this指向一個HTML元素。

這兩者簡直不相容。只有一個this,它指向當前的Player對象,而不是HTML元素。

要解決您的問題,您需要將HTML元素在創建時或傳入相關函數調用時傳遞給Player對象。

您可以將元素傳遞到基於結構Player對象是這樣的:

$.Player = function ($, element) { 
     this.element = element; 

}; 

$.Player.prototype.InitEvents = function() { 

    $(this.element).keypress(function (e) { 
     var key = e.which; 
     if (key == 100) { 
      MoveRight(); 
     } 
     if (key == 97) { 
      MoveLeft(); 
     } 
    }); 
}; 

$.Player.prototype.MoveRight = function() { 
    $(this.element).css("right", this.playerX += 10); 
} 

$.Player.prototype.MoveLeft = function() { 
    $(this.element).css("right", this.playerX -= 10); 
} 

$.Player.defaultOptions = { 
    playerX: 0, 
    playerY: 0 
}; 
+0

對不起我的無知,但我該如何使用這個類?我的意思是如果我使用它,爲什麼我在我的問題中顯示它dosnt工作。 (如果不是那麼難)你能添加一個例子嗎? (感謝您花時間回答我的問題) – samy