Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Page 1 of 2 12 LastLast
Results 1 to 15 of 23
  1. #1
    New to the CF scene
    Join Date
    Sep 2013
    Location
    Houston
    Posts
    8
    Thanks
    0
    Thanked 1 Time in 1 Post

    JavaScript nested Prototypes

    Hi,

    I recently put some code up for a Code Review and was informed that I should use this syntax:
    Code:
    function MyObject(x, y){
       this.XCoordinate = x;
       // other properties follow
    }
    MyObject.prototype = {
      draw: function(){
        // draw code ......
      },
      update: function(){
        // update code......
      };
    }
    Instead of my old method which was more like
    Code:
    function MyObject(x, y){
       this.XCoordinate = x;
       this.draw = function(){
        // draw code ......
       }
       this.update = function(){
        // update code......
       }
    }
    It was explained that this would save memory as every instance of MyObject would share the same defined methods using the first example, but using the second they would all have their own methods.

    So I went about the process of recoding a project using the proper method. It is a sudoku game so having multiple boards in memory with 81 cells all having their own methods would probably be bad. I am running into issues when I have to access methods that are nested within another object.

    Here is an example of some code that is giving me trouble.
    Code:
    // ---------------------------------- GENERATOR OBJECT ----------------------------------------------------
    function Generator(){                                     // object to generate sudokus
      this.ToGen = new DataBoard();
      var ThisSolver = new Solver(this.ToGen);
      var Interval;
    }
    Generator.prototype = {                // Generator Prototypes  
      Update: function(){                  // update function for the generator
       ThisSolver.Update();
      },
      BigBang: function(){                 // kickoff function for the generator
        Interval = setInterval(this.Update, 20);
      }
    }
    // ----------------------------------- SOLVER OBJECT ---------------------------------------------------------
    function Solver(board){   
      var ThisBoard = new DataBoard();
      CopyBoard(ThisBoard, board);
    }
    Solver.prototype = {  // Solver Prototypes
      constructor: Solver,
      Update: function(){                  
        Solve();
      },
      // other functions ....
    }
    I have tried alot of sparadic usage of this, but I am not getting the desired result.

    error is ThisSolver is undefined

    If you could point let me know the right syntax for doing this or point me to a link I would be much obliged.

  • #2
    Senior Coder Dormilich's Avatar
    Join Date
    Jan 2010
    Location
    Behind the Wall
    Posts
    3,215
    Thanks
    12
    Thanked 338 Times in 334 Posts
    Quote Originally Posted by Lesshardtofind View Post
    error is ThisSolver is undefined
    of course. ThisSolver is a local variable of the Generator function (it doesn’t matter whether you run it with or without new) and thus discarded once it run. the same goes for Interval.

    rule of thumb: every instance property of the object has to be defined using this (this.propertyname or this['propertyname'] or Object.defineProperty(this, 'propertyname', ...))

    additional note, methods should not start uppercase to differentiate between Methods and Constructors.
    The computer is always right. The computer is always right. The computer is always right. Take it from someone who has programmed for over ten years: not once has the computational mechanism of the machine malfunctioned.
    André Behrens, NY Times Software Developer

  • #3
    New to the CF scene
    Join Date
    Sep 2013
    Location
    Houston
    Posts
    8
    Thanks
    0
    Thanked 1 Time in 1 Post
    Thanks for your response.

    I am aware that var is local/private and will dissapear with scope and this is public and will exist as long as the object does, but the ambiguity of the meaning of this produces un wanted circumstances that I was hoping to avoid.

    I had also fooled myself into thinking I fixed it by not using var or this to declare, but later found out that this was just creating a global property and though deletable I still didn't want that result either.

    I have yet to stumple upon a working solution, but my research turned up many articles saying if an object was only going to have one instance it wasn't needed to use the prototype to declare the methods. This allowed me to declare commonly used types like boards and cells as prototypes to their object/function, but I kept the methods of generator and solver encapsulated in their constructor.

    additional note, methods should not start uppercase to differentiate between Methods and Constructors.
    This appears to be a preference? I could not substantiate this claim with referencial data.

    I still have yet to figure out a working example of 4-5 nested deep objects having all methods declared in the prototype. If you could provide a link or an example I would really appreciate it.

  • #4
    Master Coder felgall's Avatar
    Join Date
    Sep 2005
    Location
    Sydney, Australia
    Posts
    6,592
    Thanks
    0
    Thanked 645 Times in 635 Posts
    Quote Originally Posted by Lesshardtofind View Post
    this is public and will exist as long as the object does
    It doesn't in JavaScript - this only exists until the constructor finishes running. It may be recreated when a method is called depending on how the method is called but the safer way to provide a value that can be referenced both from the constructor and the methods is to use a closure to define a variable that exists for as long as the object does.
    Stephen
    Learn Modern JavaScript - http://javascriptexample.net/
    Helping others to solve their computer problem at http://www.felgall.com/

    Don't forget to start your JavaScript code with "use strict"; which makes it easier to find errors in your code.

  • #5
    New to the CF scene
    Join Date
    Sep 2013
    Location
    Houston
    Posts
    8
    Thanks
    0
    Thanked 1 Time in 1 Post
    Quote:
    additional note, methods should not start uppercase to differentiate between Methods and Constructors.
    This appears to be a preference? I could not substantiate this claim with referencial data.
    And of course the next video I watch tells my the WHY behind your statement.
    8:33 in the video at http://www.youtube.com/watch?v=DwYPG6vreJg if anyone who reads this later wants to know why.

    the safer way to provide a value that can be referenced both from the constructor and the methods is to use a closure to define a variable that exists for as long as the object does.
    I think this is the root of my misunderstanding. Can you elaborate? I read something similar and had a hard time understanding.

    Code:
    function MyObject(){
      this.name = "Bill";
    }
    var newObject = new MyObject();
    Since newObject is global why would its this.name property go out of scope?

    How would you declare it to prevent name from going out of scope and yet all MyObject instances still have their own individual name?

  • Users who have thanked Lesshardtofind for this post:

    Arbitrator (09-03-2013)

  • #6
    Senior Coder xelawho's Avatar
    Join Date
    Nov 2010
    Posts
    2,885
    Thanks
    56
    Thanked 539 Times in 536 Posts
    the name property doesn't go out of scope - this does (well, it doesn't, but in the global scope this tends to refer to the window object). Try it with
    Code:
    alert(newObject.name)

  • #7
    Senior Coder Dormilich's Avatar
    Join Date
    Jan 2010
    Location
    Behind the Wall
    Posts
    3,215
    Thanks
    12
    Thanked 338 Times in 334 Posts
    recommended reading for to not confuse Scope and Context: http://ryanmorr.com/understanding-sc...in-javascript/
    The computer is always right. The computer is always right. The computer is always right. Take it from someone who has programmed for over ten years: not once has the computational mechanism of the machine malfunctioned.
    André Behrens, NY Times Software Developer

  • #8
    Senior Coder Dormilich's Avatar
    Join Date
    Jan 2010
    Location
    Behind the Wall
    Posts
    3,215
    Thanks
    12
    Thanked 338 Times in 334 Posts
    out of interest, a version without Constructors
    PHP Code:
    // Solver
    var Solver = {
        
    createFrom : function _solver(board) {
            var 
    obj   Object.create(Solver.proto);
            
    obj.toGen = new DataBoard();
            
    // not sure what the CopyBoard() function does exactly
            
    return obj;
        },
        
    proto : {
            
    update : function() {
                
    // do something
            
    }
            
    // etc.
        
    }
    };

    var 
    Generator = {
        
    createWith : function _generator(solv) {
            var 
    obj    Object.create(Generator.proto);
            
    obj.solver solv;
            
    // since the interval is (currently) write-only,
            // we can set it when needed
            
    return obj;
        },
        
    proto : {
            
    update : function() {
                
    this.solver.update();
            },
            
    bigBang : function() {
                
    // attention! there is a context change in setTimeout()
                
    this.interval window.setInterval(this.update.bind(this), 20);
            }
        }
    };

    // how to use:

    // create a solver
    var mySolver Solver.createFrom(aBoard);

    // create a generator
    var myGenerator Generator.createWith(mySolver);
    // ka-boom
    myGenerator.bigBang(); 
    The computer is always right. The computer is always right. The computer is always right. Take it from someone who has programmed for over ten years: not once has the computational mechanism of the machine malfunctioned.
    André Behrens, NY Times Software Developer

  • #9
    Senior Coder Arbitrator's Avatar
    Join Date
    Mar 2006
    Location
    Splendora, Texas, United States of America
    Posts
    3,300
    Thanks
    28
    Thanked 275 Times in 269 Posts
    Quote Originally Posted by Lesshardtofind View Post
    I still have yet to figure out a working example of 4-5 nested deep objects having all methods declared in the prototype. If you could provide a link or an example I would really appreciate it.
    Direct use of prototypes can be circumvented via the Object.create method unless you're modifying built-in objects like HTMLElement. This also allows you to declare your object as an object, rather than a function.

    Code:
    <!doctype html>
    <html lang="en">
    	<head>
    		<meta charset="utf-8">
    		<title>Demo</title>
    		<script>
    			var baseObject = {};
    			var childObject1 = Object.create(baseObject);
    			var childObject2 = Object.create(childObject1);
    			var childObject3 = Object.create(childObject2);
    			var childObject4 = Object.create(childObject3);
    			baseObject.sayHello = function () {
    				alert("Hi!");
    			};
    			childObject4.sayHello();
    		</script>
    	</head>	
    	<body></body>
    </html>
    If you want to use the prototype property and the new keyword and get the expected object-inherits-from-object behavior, then you need to do a bit of gymnastics where the pattern for every inheritance process is to: (A) create a constructor function, (B) explicitly assign its prototype to the object you want to inherit from, and (C) create a new instance of the constructor.

    Edit: I reworked the code to separate the object variables from the constructors. This allows use of proper capitalization for each. I also changed baseObject from a function to an object, though the code works either way.

    Code:
    <!doctype html>
    <html lang="en">
    	<head>
    		<meta charset="utf-8">
    		<title>Demo</title>
    		<script>
    			var baseObject = {};
    			function ChildObject1() {};
    			ChildObject1.prototype = baseObject;
    			var childObject1 = new ChildObject1();
    			function ChildObject2() {};
    			ChildObject2.prototype = childObject1;
    			var childObject2 = new ChildObject2();
    			function ChildObject3() {};
    			ChildObject3.prototype = childObject2;
    			var childObject3 = new ChildObject3();
    			function ChildObject4() {};
    			ChildObject4.prototype = childObject3;
    			var childObject4 = new ChildObject4();
    			baseObject.sayHello = function () {
    				alert("Hi!");
    			};
    			childObject4.sayHello();
    		</script>
    	</head>	
    	<body></body>
    </html>
    As Douglas Crockford points this out in the video you cited at 17:20, you can simplify this process with an intermediary function. It's still not as elegant as Object.create, but it works.

    Code:
    <!doctype html>
    <html lang="en">
    	<head>
    		<meta charset="utf-8">
    		<title>Demo</title>
    		<script>
    			function newInstance(object) {
    				function F() {};
    				F.prototype = object;
    				return new F();
    			}
    			function baseObject() {};
    			var childObject1 = newInstance(baseObject);
    			var childObject2 = newInstance(childObject1);
    			var childObject3 = newInstance(childObject2);
    			var childObject4 = newInstance(childObject3);
    			baseObject.sayHello = function () {
    				alert("Hi!");
    			};
    			childObject4.sayHello();
    		</script>
    	</head>	
    	<body></body>
    </html>
    Last edited by Arbitrator; 09-03-2013 at 10:25 PM. Reason: I reworked the second code block. See the post.
    For every complex problem, there is an answer that is clear, simple, and wrong.

  • #10
    New to the CF scene
    Join Date
    Sep 2013
    Location
    Houston
    Posts
    8
    Thanks
    0
    Thanked 1 Time in 1 Post
    Thanks for the information. I keep stumbling on videos and sites that talk about avoiding usage of the new keyword. I haven't really attempted the object.create. Since I am 70% through completition on this program I'm not going to change styles in the middle of it, but I think I should move towards some better understanding of the Object.create on my next project.

    @Dormilich the CopyBoard is to pass the generated hints board from the Generator to the Solver. The Solver then will produce a boolean to tell the Generator if the board that it currently has stored in memory is a solvable sudoku or if it should erase it and generate a new one. I didn't impliment it in a constructor as I had originally imagined but wrote a method call .set that set the Solver to a board passed to it.

    I have it generating based on randomly generated values that are inserted based on the rules of a sudoku and then validating, but I am finding JavaScript to be rather slow at this process compared to a C++ program I had written that did the same.

    I am not sure if I can make the solver smart enough or if I'm going to have to resort to the random rotating and swapping of rows, columns, and grids on a known sudoku to generate new ones.

  • #11
    Senior Coder Dormilich's Avatar
    Join Date
    Jan 2010
    Location
    Behind the Wall
    Posts
    3,215
    Thanks
    12
    Thanked 338 Times in 334 Posts
    Quote Originally Posted by Lesshardtofind View Post
    I have it generating based on randomly generated values that are inserted based on the rules of a sudoku and then validating, but I am finding JavaScript to be rather slow at this process compared to a C++ program I had written that did the same.
    a) compiled vs. interpreted languages. you have to put in some effort to get JS run nearly as fast as compiled code (and of course that depends on the JS engine used, i.e. V8 needs other modifications than JagerMonkey)

    b) if you can run it in the background (logic-wise), use a WebWorker
    The computer is always right. The computer is always right. The computer is always right. Take it from someone who has programmed for over ten years: not once has the computational mechanism of the machine malfunctioned.
    André Behrens, NY Times Software Developer

  • #12
    Senior Coder Dormilich's Avatar
    Join Date
    Jan 2010
    Location
    Behind the Wall
    Posts
    3,215
    Thanks
    12
    Thanked 338 Times in 334 Posts
    Quote Originally Posted by Lesshardtofind View Post
    the CopyBoard is to pass the generated hints board from the Generator to the Solver. The Solver then will produce a boolean to tell the Generator if the board that it currently has stored in memory is a solvable sudoku or if it should erase it and generate a new one. I didn't impliment it in a constructor as I had originally imagined but wrote a method call .set that set the Solver to a board passed to it.
    then I would restructure the logic.
    Code:
    do {
      board = new DataBoard();
    }
    while (solver.valid(board));
    this.board = board;
    The computer is always right. The computer is always right. The computer is always right. Take it from someone who has programmed for over ten years: not once has the computational mechanism of the machine malfunctioned.
    André Behrens, NY Times Software Developer

  • #13
    New to the CF scene
    Join Date
    Sep 2013
    Location
    Houston
    Posts
    8
    Thanks
    0
    Thanked 1 Time in 1 Post
    b) if you can run it in the background (logic-wise), use a WebWorker
    Yea I've been reading up on futures and laters to allow things like that to run and then execute when they finish but not slow anythine else down. I was thinking about doing something similiar.

    My first idea was to just gererate a "daily" solution and have it saved on the Server so that it was always pulled up on a user loading a page this would save them from having to wait for one to be generated. I could then generate a new one in the background while they played through the first one. Then if they clicked "play again" I could deliver that one and if they navigate away from the page I could deliver that generated sudoku back to the server for the next user (though I haven't done alot of AJAX I believe it can act as an intermediary for stuff like this.)

    Code:
    do {
      board = new DataBoard();
    }
    while (solver.valid(board));
    this.board = board;
    Do functions have a built in copy constructor? I had writen the CopyBoard function for two reasons.
    1. I had no idea how JavaScript handles the statement ThisObejct = ThatObject, and I read there was no operator overloading in JavaScript.
    2. I have to pass the data from a DataBoard(only data) to a GameBoard(data and graphical) and the CopyBoard function copies only data that they share.

  • #14
    Senior Coder Dormilich's Avatar
    Join Date
    Jan 2010
    Location
    Behind the Wall
    Posts
    3,215
    Thanks
    12
    Thanked 338 Times in 334 Posts
    Quote Originally Posted by Lesshardtofind View Post
    Do functions have a built in copy constructor?
    no.

    simple rule: Functions are Objects (sounds weird if you come from a class-based language) and some Objects should not be copied because of circular references (e.g. many DOM Objects have them)

    Quote Originally Posted by Lesshardtofind View Post
    I had writen the CopyBoard function for two reasons.
    1. I had no idea how JavaScript handles the statement ThisObejct = ThatObject, and I read there was no operator overloading in JavaScript.
    2. I have to pass the data from a DataBoard(only data) to a GameBoard(data and graphical) and the CopyBoard function copies only data that they share.
    1. it creates a reference to ThatObject (all non-primitive values (i.e. all except null, undefined & the String/Number/Boolean literals) are copied by reference)

    there is one instance of (native) operator overloading: + (addition & concatenation)

    2. so DataBoard and GameBoard have different data? so you want to do something like an array intersect? but that throws the question, whether you intend to remove data from GameBoard or not, because data that they share do not need to be copied since they are already there.
    The computer is always right. The computer is always right. The computer is always right. Take it from someone who has programmed for over ten years: not once has the computational mechanism of the machine malfunctioned.
    André Behrens, NY Times Software Developer

  • #15
    New to the CF scene
    Join Date
    Sep 2013
    Location
    Houston
    Posts
    8
    Thanks
    0
    Thanked 1 Time in 1 Post
    You have been really helpful thus far and I really appreciate all the information you have volunteered. I hope you don't mind if I push the chain a little further here.

    1. it creates a reference to ThatObject (all non-primitive values (i.e. all except null, undefined & the String/Number/Boolean literals) are copied by reference)

    there is one instance of (native) operator overloading: + (addition & concatenation)
    When you say reference in JavaScript does this imply that the variable ThisObject wouldn't actually take up any space in memory but rather point to ThatObject so if I made a change to ThisObject the change would actually take effect in ThatObject.

    This is the way I undertstand references such that in a function pass
    Code:
    function addTo(x, y){
      x += y;
    }
    Since whatever I hand to this function will be changed because functions pass by reference in JavaScript whereby a classical language you would have to use a symbol to tell the compiler this was a reference such as the & operater in C++.

    2. so DataBoard and GameBoard have different data? so you want to do something like an array intersect? but that throws the question, whether you intend to remove data from GameBoard or not, because data that they share do not need to be copied since they are already there.
    I think my problem is I still dont' think like a JavaScript programmer yet. I made three object handlers in this program. The Game, the Solver, and the Generator. They all have their own boards so they can work independantly of each other and yet pass to each other using the Copy function. This will allow you to generate more puzzles in the background while the Game runs because they don't share and reference the same data point but just pass important data and clear the rest.

    The Graphical board and the Data Board only share two similiar traits which is the Value of a space (1-9) and the boolean array of size nine which holds all the "possible" numbers in a given square. To solve a sudoku you need to know what numbers are and aren't possible in any given square and I planned on displaying this information to a user based on the difficulty level chosen. Because of this the copy function looked something like.

    Code:
    function CopyBoard(to, from){
      for(var row = 0; row < 9; row++){
        for(var column = 0; column < 9; column++){
          to.Cells[row][column].Value = from.Cells[row][column].Value;
          for(var number = 0; number < 9; number++){
            to.Cells[row][column].IsPossible[number] = from.Cells[row][column].IsPossible[number];
          }
        }
      }
    }
    I am probably still thinking more classical than I need too. I've watched that video I linked aboved twice now and I just keep picking stuff up from it and struggle with other concepts. This whole parasitic inheritence concept is completely new, but I can see his point that people (like me) bringing baggage from other languages into this language only stops them from realizing its full potential.


  •  
    Page 1 of 2 12 LastLast

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •