I am trying to understand objects in javascript. Here is the code:
var fn={};
var canvas;
var ctx;
fn.game=function(width,height,inSide,name){
this.canvas2=document.getElementById(inSide).innerHTML = "<canvas id="+name+" style='width:"+width+";height:"+height+";'>Your browser does not support the Canvas Element.</canvas>";
this.canvas=document.getElementById(name);
this.ctx=this.canvas.getContext("2d");
document.getElementById(inSide).style.width=width;
document.getElementById(inSide).style.height=height;
canvas=document.getElementById(name);
ctx=this.canvas.getContext("2d");
this.width=width;
this.height=height;
canvas.width=width;
canvas.height=height;
this.add={
};
this.add.state=function(name){
this[name]=3;
};
};
var game=new fn.game(640,480,"game","canvas");
game.addState("play");
when I am referencing this["name"] I am trying to refer this to fn.game, but that dous not work because this references the most local object. Any ideas on how to do this?
As you said, it references the most local object, to do what you explained :
...
fn.game=function(width,height,inSide,name){
var that = this;//expose this of fn.game to this scope
...
this.add={
};
this.add.state=function(name){
that[name]=3;//access this of fn.game
};
};
There are a couple of ways to do this, and it depends on the way you're doing it, although I think the biggest issue you've got is that your object has no declared function of addState() so when I tried to run your code it just gave me an error. In the code below I changed it, and it should work how you want it to currently.
var fn = {};
var canvas;
var ctx;
fn.game = function(width, height, inSide, name) {
this.canvas2 = document.getElementById(inSide).innerHTML = "<canvas id=" + name + " style='width:" + width + ";height:" + height + ";'>Your browser does not support the Canvas Element.</canvas>";
this.canvas = document.getElementById(name);
this.ctx = this.canvas.getContext("2d");
document.getElementById(inSide).style.width = width;
document.getElementById(inSide).style.height = height;
canvas = document.getElementById(name);
ctx = this.canvas.getContext("2d");
this.width = width;
this.height = height;
canvas.width = width;
canvas.height = height;
this.add = {
};
this.addState = function(name) {
this[name] = 3;
console.log(this);
};
};
var game = new fn.game(640, 480, "game", "canvas");
game.addState("play");
<div id="game"></div>
HOWEVER
If you'd like to have that same syntax as before, of game.add.state(), then something like either of the below examples should work:
Example 1
Link to Function.Prototype.Bind
//Rest of code
this.add={};
this.add.state = function(name){
this[name]=3;
}.bind(this)
//Rest of code
Example 2
Javascript Variables and Scope
//Rest of code
this.add={};
var self = this;
this.add.state = function(name){
self[name]=3;
}
//Rest of Code
every time you are inside a function() the meaning of this changes to the current function
all you need to do is save the reference to the object you want to access
fn.game=function(width,height,inSide,name){
var self = this;
this.add.state=function(name){
self[name]=3;
};
};
In order for this to mean mean fn.game, you would need to do something more like:
var doc = document, bod = doc.body;
function E(e){
return doc.getElementById(e);
}
function C(t){
return doc.createElement(t);
}
function FnGameAdd(){
this.state = function(popertyName){
this[propertyName] = 3;
}
}
function FnGame(canvasId, width, height, inside){
// style with CSS
inside.innerHTML = "<canvas id='"+canvasId+"'>Your browser does not support the Canvas Element.</canvas>";
var cv = this.canvas = E(canvasId);
cv.height = height; cv.width = width; this.ctx = cv.getContext('2d');
this.add = new FnGameAdd;
};
}
var fn = {};
fn.game = function(canvasId, width, height, inside){
// this.prop = 'belongs to fn';
return new FnGame(canvasId, width, height, inside);
}
new fn.game('canvas', 640, 480, E('game'));
/* keep this for fun of creating new Object literals, not needed here
Object.create = Object.create || function(obj){
function F(){}; F.prototype = obj;
return new F;
}
var newObj = Object.create(fn);*/
Related
So I am getting a "Uncaught TypeError: Cannot read property '0' of undefined
at update" at line 42, which is this one:
init.ctx.moveTo(this.trail[0].x,this.trail[0].y);
from the following code:
window.onresize = function(){
init.canvas.width = window.innerWidth;
init.canvas.height = window.innerHeight;
//updateComponents();
}
var init = {
canvas: new Object(),
ctx: new Object(),
constructCanvas: function(){
this.canvas = document.getElementById("canvas");
this.ctx = this.canvas.getContext("2d");
this.canvas.width = window.innerWidth;
this.canvas.height = window.innerHeight;
}
}
init.constructCanvas();
var background = {
color: "green",
refresh: function(){
init.ctx.fillStyle = this.color;
init.ctx.fillRect(0,0,init.canvas.width,init.canvas.height);
}
}
//background.refresh();
function updateComponents(){
background.refresh();
}
function WalkingLine(arguments){
this.frames = 0;
this.trail = [];
this.walkLength = 5;
this.position = arguments.position;
this.color = "black";
this.trail[0] = this.position;
}
WalkingLine.prototype = {
update: function(){
init.ctx.beginPath();
init.ctx.moveTo(this.trail[0].x,this.trail[0].y);
var i;
for(i=1;i<this.trail.length;i++)
init.ctx.lineTo(this.trail[i].x,this.trail[i].y);
init.ctx.stroke();
this.generateNext();
},
genarateNext: function(){
this.trail[this.trail.length] = {x:this.trail[this.trail.length-1].x+5,y:this.trail[this.trail.length-1].y};
init.ctx.lineTo(this.trail[this.trail.length-1].x,this.trail[this.trail.length-1].y);
inti.ctx.stroke();
}
};
var one = new WalkingLine({position:{x:100,y:100}});
setTimeout(one.update,1000);
So i dont understand why i am apparently trying to access an invalid index in the array because i explicitly set table[0] in the constructor of the WalkingLine class yet despite that it still says it is an uncaught type Error.
You lose context:
setTimeout(one.update,1000);
That way you pass only update without the one, so when its called later it does not know where it belongs to. You either need to call it directly ( inside an arrow function):
setTimeout(()=>one.update(),1000);
or you need to bind the function to one:
setTimeout(one.update.bind(one),1000);
I'm having a problem while loading pictures in my javascript. Seems that the .onload function is never called and so the picture is not marked as loaded. Can you help?
Here is the code:
//image loader
var img = function (source){
this.loaded = false;
this.image = new Image();
this.image.onload = function () {
this.loaded = true;
};
this.image.src = source;
}
//default component definition
var component = function (x, y){
this.x = x;
this.y = y;
this.draw = function (offsetX, offsetY, img){
if(img.loaded){
ctx.drawImage(img.image,
this.x + offsetX,
this.y + offsetY,
img.image.width, img.image.height);
}
}
}
Thanks
Context #1
this.image.onload = function () {
this.loaded = true;
};
this referes to [object HTMLImageElement], not to the img instance.
Context #2
Now, changing the code to:
this.image.onload = function () {
this.loaded = true;
}.bind(this);
When you do new img("http://serban.ghita.org/imgs/serban.jpg");, this will refer to your [object Object].
Context #3
Now, If you do img("http://serban.ghita.org/imgs/serban.jpg");, without new, this will refer to [object Window].
Solution
It depends on the context of this.
You change it with bind
Or by declaring and external var _this = this; and then use _this.loaded = true; inside onload.
Code: https://jsbin.com/pasumab/edit?js,console
How to update universe variable css using create and update methods below:
var gravity = {
universe: function (width, height, color) {
this._width = width;
this._height = height;
this._color = color;
var universe;
var create = function () {
universe = document.createElement("div");
universe.style.border = "5px solid #DDD";
universe.style.overflow = "hidden";
document.body.appendChild(universe);
};
var update = function () {
universe.style.width = this._width + "px";
universe.style.height = this._height + "px";
universe.style.backgroundColor = this._color;
};
create();
update();
}
}
Update method doesn't work.
your update method "doesnt work" because when you call it, this references the window object.
if you wanted it to work, one possible solution would be to set var that = this; outside of the update method and replace all references to this with that inside the method.
this should clear things up a bit
I'm new using JS. I want to keep all of the information about an object in one place.
So I've made this function:
function Obiekt(img) {
this.img = img;
this.ready = false;
this.image = new Image();
this.image.src = this.img;
this.image.onload = function() {
ready = true;
};
this.x = 0;
this.y = 0;
this.rotation = 0;
}
Then I've made my object, named hero.
var hero = new Obiekt("images/hero.png");
Problem is, hero.ready is always false and I can't draw this.
if (hero.ready) {
ctx.drawImage(hero.image, 0, 0);
}
Can you help me?
Two problems :
ready can't be found
If your image is cached (depending on the browser), the order you used can't work as the image isn't loaded after you set the callback.
Here's a solution :
var _this = this;
this.image.onload = function() {
_this.ready = true;
};
this.image.src = this.img;
(and I'd add that the naming isn't very good : I'd prefer imgsrc over img)
I'm a beginner with OOP coding in javascript.
I'm trying to set a size of a class. But i got an error in my code.
(function($) {
Block = function() {
var self = this;
this.el = $('<div></div>');
}
Block.prototype.appendTo = function(parent) {
this.el.appendTo(parent);
}
Block.prototype.setSize = function(width, height) {
var self = this;
this.width = width;
this.height = height;
}
})(jQuery);
This is how i call the class:
var block1 = new Block();
block1.appendTo('body').setSize(100,100);
In the console i get:
Uncaught TypeError: Cannot call method 'setSize' of undefined
You are calling setSize on the return value of appendTo. However, appendTo returns nothing (undefined) and as such it throws an Error when you try and call setSize on it.
The solution to this is to return the Block object from your appendTo function, like so:
(function($) {
Block = function(width, height) {
this.el = $('<div></div>');
if (width !== undefined && height !== undefined) {
this.width = width;
this.height = height;
}
}
Block.prototype.appendTo = function(parent) {
this.el.appendTo(parent);
return this;
}
Block.prototype.setSize = function(width, height) {
this.width = width;
this.height = height;
}
})(jQuery);