简体   繁体   中英

Javascript class method declaration throwing token error

I am having a problem defining a class method:

this.method = function(){...}

I get an error thrown at the "." after "this".

If I declare the method directly using method(){...} , I am unable to reference it in other methods as it shows that the method is undefined.

The method I want to deifne is shuffleBoard() . How do I do it?

class Board {

   constructor(size,boardId){
       this.boardId = boardId;
       switch(size){
           case "medium":
               var boardSize = 560;
               var tiles = 7*7;
               break;
           case "large":
               boardSize = 720;
               tiles = 9*9;
               break;
           default:
               boardSize = 320;
               tiles = 4*4;
               break;
       }

       var container = $(this.boardId+" .tiles-container");

           var row = 0;
           var loopArray = [];
       for(var i = 0;i < tiles; i++){
           var tile = document.createElement("div");
           loopArray.push(i);
           var text = i+1;
           tile.setAttribute("index",i+1);
           tile.id = i+1;
           if(i == tiles - 1){
               var empty = "empty"
           }
           tile.setAttribute("class","tile "+empty);
           tile.innerText = text;
           container.append(tile);
           (function(){
           tile.onclick = function(){
               var tileObject = new Tile(this.getAttribute("index"));
               console.log(tileObject.move());
           }
           })()

           var prevRow = row;

           if(i%4 == 0 && i != 0){
               row++
           }

           if(row > prevRow){
               var positionX = 0;
           }

           else{
               var positionX = (i%4)*80;
           }

           var positionY = row*80;
           tile.style.top=positionY+"px";

           tile.style.left=positionX+"px";
           console.log(i+"---"+row+"////"+prevRow);
       }
       setTimeout(function(){this.shuffleBoard(loopArray);},4000);

       return container;
   }

   this.shuffleBoard = function(arr){
       var i = 0;
       console.log(this.boardId);
       $(this.boardId+" .tiles-container tile").forEach(function(el){
           var shuffled = shuffle(arr);
           el.innerText = shuffled[i];
           arr.pop(arr[i]);
           i++
       });
   }

}

It seems like you are using ES6 syntax. In ES6 write functions like

shuffleBoard() {
    // rest of the code
}

and to access it use this keyword. like this.shuffleBoard() .

To call it in setTimeout, use arrow functions

setTimeout(() => { this.shuffleBoard(loopArray); }, 4000);

1.You have to use an arrow function to keep the scope, because otherwise this would be pointing to the new function created in the timeout.

setTimeout(() => {
      this.shuffleBoard(loopArray);
    }, 4000);

2.The constructor mustn't return anything because it prevents it from returning the object it constructs

3.jQuery uses .each() to iterate over jQuery objects instead of .forEach() .

I put the notes directly in the code as comments as well:

 class Board { constructor(size, boardId) { this.boardId = boardId; switch (size) { case "medium": var boardSize = 560; var tiles = 7 * 7; break; case "large": boardSize = 720; tiles = 9 * 9; break; default: boardSize = 320; tiles = 4 * 4; break; } var container = $(this.boardId + " .tiles-container"); var row = 0; var loopArray = []; for (var i = 0; i < tiles; i++) { var tile = document.createElement("div"); loopArray.push(i); var text = i + 1; tile.setAttribute("index", i + 1); tile.id = i + 1; if (i == tiles - 1) { var empty = "empty" } tile.setAttribute("class", "tile " + empty); tile.innerText = text; container.append(tile); (function() { tile.onclick = function() { var tileObject = new Tile(this.getAttribute("index")); console.log(tileObject.move()); } })() var prevRow = row; if (i % 4 == 0 && i != 0) { row++ } if (row > prevRow) { var positionX = 0; } else { var positionX = (i % 4) * 80; } var positionY = row * 80; tile.style.top = positionY + "px"; tile.style.left = positionX + "px"; console.log(i + "---" + row + "////" + prevRow); } setTimeout(() => { //use arrow function to keep the scope this.shuffleBoard(loopArray); }, 4000); //return container; returning the container here prevents the constructor from returning the constructed object } shuffleBoard(arr) { var i = 0; console.log(this.boardId); $(this.boardId + " .tiles-container tile").each(function(el) { //jQuery uses .each instead of forEach var shuffled = shuffle(arr); el.innerText = shuffled[i]; arr.pop(arr[i]); i++ }); } } let board = new Board("medium", "myboard"); console.log(board.shuffleBoard); board.shuffleBoard([]); 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 

shuffleBoard = function(arr){
    // rest of code
})

Then you can use method as:

let board = new Board()
board.shuffleBoard()

way1:move this.propertyName to constructor

class Board{

   constructor(size,boardId){
       this.boardId = boardId;
       switch(size){
           case "medium":
               var boardSize = 560;
               var tiles = 7*7;
               break;
           case "large":
               boardSize = 720;
               tiles = 9*9;
               break;
           default:
               boardSize = 320;
               tiles = 4*4;
               break;
       }

       var container = $(this.boardId+" .tiles-container");

           var row = 0;
           var loopArray = [];
       for(var i = 0;i < tiles; i++){
           var tile = document.createElement("div");
           loopArray.push(i);
           var text = i+1;
           tile.setAttribute("index",i+1);
           tile.id = i+1;
           if(i == tiles - 1){
               var empty = "empty"
           }
           tile.setAttribute("class","tile "+empty);
           tile.innerText = text;
           container.append(tile);
           (function(){
           tile.onclick = function(){
               var tileObject = new Tile(this.getAttribute("index"));
               console.log(tileObject.move());
           }
           })()

           var prevRow = row;

           if(i%4 == 0 && i != 0){
               row++
           }

           if(row > prevRow){
               var positionX = 0;
           }

           else{
               var positionX = (i%4)*80;
           }

           var positionY = row*80;
           tile.style.top=positionY+"px";

           tile.style.left=positionX+"px";
           console.log(i+"---"+row+"////"+prevRow);
       }
       setTimeout(function(){this.shuffleBoard(loopArray);},4000);

       this.shuffleBoard = function(arr) {
         var i = 0;
         console.log(this.boardId);
         $(this.boardId + " .tiles-container tile").forEach(function(
           el
         ) {
           var shuffled = shuffle(arr);
           el.innerText = shuffled[i];
           arr.pop(arr[i]);
           i++;
         });
       }

       return container;
   }
}

way2:change this.propertyName to a method in className.prototype

class Board {
  constructor(size, boardId) {
    this.boardId = boardId;
    switch (size) {
      case "medium":
        var boardSize = 560;
        var tiles = 7 * 7;
        break;
      case "large":
        boardSize = 720;
        tiles = 9 * 9;
        break;
      default:
        boardSize = 320;
        tiles = 4 * 4;
        break;
    }

    var container = $(this.boardId + " .tiles-container");

    var row = 0;
    var loopArray = [];
    for (var i = 0; i < tiles; i++) {
      var tile = document.createElement("div");
      loopArray.push(i);
      var text = i + 1;
      tile.setAttribute("index", i + 1);
      tile.id = i + 1;
      if (i == tiles - 1) {
        var empty = "empty";
      }
      tile.setAttribute("class", "tile " + empty);
      tile.innerText = text;
      container.append(tile);
      (function() {
        tile.onclick = function() {
          var tileObject = new Tile(this.getAttribute("index"));
          console.log(tileObject.move());
        };
      })();

      var prevRow = row;

      if (i % 4 == 0 && i != 0) {
        row++;
      }

      if (row > prevRow) {
        var positionX = 0;
      } else {
        var positionX = (i % 4) * 80;
      }

      var positionY = row * 80;
      tile.style.top = positionY + "px";

      tile.style.left = positionX + "px";
      console.log(i + "---" + row + "////" + prevRow);
    }
    setTimeout(function() {
      this.shuffleBoard(loopArray);
    }, 4000);
    return container;
  }
  shuffleBoard(arr) {
    var i = 0;
    console.log(this.boardId);
    $(this.boardId + " .tiles-container tile").forEach(function(el) {
      var shuffled = shuffle(arr);
      el.innerText = shuffled[i];
      arr.pop(arr[i]);
      i++;
    });
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM