JS create custom object with self as parameter - javascript

I want to pass along "myEvent" through to "myFunction" at the end but in the object "Event", "myEvent" is undefined.
var myEvent = new Event(window,"click",myFunction,myEvent);
Event = function(target,type,func,parameter){
console.log(parameter) //undefined
var eventFunction = function(){
func(parameter)
}
this.delete = function(){
target.removeEventListener(type,eventFunction)
}
target.addEventListener(type,eventFunction);
}
myFunction(parameter){
console.log(parameter); // says undefined but I want the object "myEvent"
}
Sry for bad english

Use var that = this inside Constructor root level, then func(that) inside eventFunction. No need to explicitly pass along a reference to the newly created object, its already there in your constructor function.
If u need to explicitly pass along the myEvent reference, do:
var wrapper = {myEvent: {}};
wrapper.myEvent = new Event(...,wrapper.myEvent);

Related

JavaScript scope issue (this)

I have tried to organize my code in an object oriented way (as explained in MDN). In my case however, this refers to the window object. Because of that I get the error
Uncaught TypeError: Cannot read property 'render' of undefined
in
this.renderer.render(this.stage);
Why does this refer to the window object when it doesn't on MDN?
var GAME = GAME || {};
GAME.Application = function() {
this.renderer = PIXI.autoDetectRenderer(800, 600,{backgroundColor : 0x1099bb});
document.getElementById("game").appendChild(this.renderer.view);
this.stage = new PIXI.Container();
requestAnimationFrame(this.render);
}
GAME.Application.prototype.render = function() {
this.renderer.render(this.stage);
}
var app = new GAME.Application();
You need to bind your render function. This is probably the most straight forward solution.
requestAnimationFrame(this.render.bind(this));
Or instead, you could do
var context = this;
requestAnimationFrame(function() {
context.render();
});
Or you could avoid creating the free variable and use an IIFE
requestAnimationFrame((function(context) {
context.render();
})(this)));
Or, if you're using ES6, you can use an arrow function
requestAnimationFrame(() => this.render());
Another easy improvement you could make is passing the render element into your Application constructor
function Application(elem) {
this.renderer = ...
elem.appendChild(this.renderer.view);
}
new Application(document.getElementById("game"));
Lets talk about this, context, and functions
A good way to think about it, is that this refers to the object on the left of the . of the method that calls it.
var someObj = {
name:'someObj',
sayName: function(){
console.log(this.name);
}
};
someObj.sayName(); // prints someObj
Functions that are not methods of an object are bound to the window object.
window.name = 'window';
function sayName(){
console.log(this.name);
}
sayName(); //prints window
The above is equivalent to
window.sayName(); // window is on the left of the dot, so it is `this`
When you pass a method of an object as a parameter, or assign it to a variable, it loses its original context. Below, the sayName method of someObj loses someObj as the context and gains someOtherObj.
var someOtherObj = {
name:'someOtherObj'
};
someOtherObj.sayName = someObj.sayName;
someOtherObj.sayName(); // prints someOtherObj
To get around it, You can bind a context to a function
var yetAnotherObj = {
name: 'yetAnotherObj'
};
var sayYetAnotherObj = sayName.bind(yetAnotherObj);
sayYetAnotherObj(); // prints yetAnotherObj
Or pass an anonymous function that calls the the method on the object itself
var OneLastObj = function(){
var self = this;
this.someValue = aFunctionTakingAcallback(function(){
return self.doSomeStuff();
});
}
Something to remember when passing functions around as a parameters is that you are passing a reference to the function. The function itself is not bound to the object that it may be a method of.

not able to change a value assigned to this object using .bind

I'm using angular to develop a web app and I'm trying to use a function's .bind method to assign the this value on a method of one of my controllers. It looks like this:
var welcomeCtrl = function (userManager) {
this.partnerName = userManager.getName('partner');
this.yourName = userManager.getName('you');
this.beginScan = false;
var self = this;
};
welcomeCtrl.prototype.scanThumb = function (callback) {
function doScan() {
alert(this);
alert(this.beginScan);
this.finishedScanning = callback;
this.beginScan = true;
}
doScan.bind(welcomeCtrl)();
};
So what happens is that a directive passes the scanThumb method to a service which executes it, which should then trigger another directive waiting for this.beginScan to be true.
Since its the service that calls the method and it is not called from the welcomCtrl class, I need to bind this back to welcomeCtrl so I use .bind and pass in welcomeCtrl
This should work, when I do alert(this) the welcomeCtrl function definition alerts fine, but when I do alert(this.beginScan) I get Undefined
Am I not understanding how the .bind method works in this circumstance?
Whenever you are using an object's inner function (in this case, welcomeCtrl) this refers to the current object.
Take the following example:
var Foo = function(){
this.thing = 'bar';
}
Foo.prototype.setThing = function(newthing){
//our inner function
function doInnerThing(){
//this is now bound to our current Foo instance
console.log(this);
//setting our current Foo.thing to new value
this.thing = newthing;
};
//fire function, bound to current object scope (Foo)
doInnerThing.bind(this)();
};
Foo.prototype.doThing = function(){
alert(this.thing);
};
var newFoo = new Foo();
var newFoo2 = new Foo();
newFoo.setThing('newFoo');
newFoo.doThing(); //alerts 'newFoo', the overridden value
newFoo2.doThing();//alerts 'bar', the base value
As #Jesse Kernaghan suggested I was simply was passing the uninitiated constructor as the the thisParam. I fixed this by modifying my service to take 2 parameters, a callback, and a thisParam. I had then had to pass in the scope as the thisParam from my directive, and in my service call the callback with a .bind(thisParam) and now everything works.

javascript namespace scope

I'm learning javascript , so don't kill me.
I'm defining more different namespaces like this :
var name_Class = function(){
this.variable_name_1 = {}
this.method_name_1 = function() {}
}
and then..
var second_name_Class = function(){
this.variable_name_1 = {}
this.method_name_1 = function() {}
}
If i define and Initialiaze a variable in the first one and I try to call it in the second one , e.g. if a write c = new name_Class() it , e.g. redefine every array to [] so I cannot get the value I gave it before. Can you help me?
I'm not sure you understand what you're doing.
This
var name_Class = function(){
this.variable_name_1 = {}
this.method_name_1 = function() {}
}
defines a constructor function called name_Class (as an aside, constructors should have their first character capitalized by convention)
This
var c = new name_Class();
creates an object using that constructor. The new object is created and the constructor is bound to that object and called, setting the variable_name_1 and method_name_1 properties of the new object c. Each time you assign new name_Class() to a variable it will create a completely new object which has the constructor bound to it. Any changes you made to other objects created to the function will not have an effect on this new variable.
All of this is completely unrelated to your second Constructor, which you can use in the same way and is not affected at all by your first one.
Neither of these things are technically namespaces, they're classes or types. A namespace generally refers to a top level variable that other variables are defined as properties on. By default variables are defined on the global namespace, which for browsers is the window.
So to create your new object with type name_Class on a namespace namespace1 for instance, you could do
var namespace1 = {};
namespace1.c = new name_Class();
You can pass in arguments if you're looking to set values on an instance. eg
var Swatch = function(){
this.color = arguments[0] || 'green';
this.callback = arguments[1] || function() {
alert(this.color);
}
this.callback();
}
//defaults to green if no args are passed
var green = new Swatch();
//or pass in your own values
var red = new Swatch('red',function(){
alert('New swatch created with color '+this.color);
});

How do I retain the properties of a Javascript object while changing the object's constructor to an instance function

I have an instance function in javascript and for naming conventions I have other instance function added as property of the first instance function object. It's better illustrated in the following working JavaScript.
var MyModule = (function() { // instance function
return function() {
console.log("ran MyModule");
}
}());
MyModule.RelatedModule = (function() { //second instance function is a property of first instance function object
return function() {
console.log("ran RelatedModule");
}
}())
var inst1 = new MyModule(), // logs "ran MyModule"
inst2 = new MyModule.RelatedModule(); // logs "ran RelatedModule"
This works as intended with no errors. What I'd like to do though is to create the function definition for MyModule after I've created the MyModule object, can anyone help me achieve this? I've illustrated my attempts below.
var MyModule = {}; // create object first, try to set a constructor on it later
MyModule.RelatedModule = (function() { // add properties to the MyModule object
return function() {
console.log("ran RelatedModule");
}
}())
// the following does not work, I'd like to set the `MyModule` constructor instance function and retain the `MyModule.RelatedModule` property
MyModule.constructor = (function() {
return function() {
console.log("ran MyModule");
}
}());
So, how do I retain the properties of an object and change it's constructor?
You're confusing a couple of concepts. In your first example, MyModule doesn't have a constructor, it is a constructor. That is, it's a function object that you intend to use with the new operator to create new objects. Those objects will have a constructor property that points back to MyModule (the function that created them). Changing this constructor property won't have any effect on MyModule; that property is just a pointer back to the function that instantiated the object.
In other words, you can't change MyModule's constructor. That's a meaningless statement.
Now, when you write:
var MyModule = {};
...you create a new object whose constructor property is Object():
console.log(MyModule.constructor) // prints Object()
Again, changing this property doesn't really do much (except obfuscate some useful book-keeping).
At this point MyModule is just a plain-old object. It's not a function at all. That's why you're getting the "not a function" error. Because it's not, but you're trying to use it as though it is. If you want that name to refer to a function (i.e. to a different object) then you're going to lose all references to any properties you previously set, because you're pointing at an entirely new object.
That's just the way it is.
Now, you could save a reference to the object that contains all those previously-set properties and copy them back into MyObject once you've pointed that name at a function. But I'm not sure what the point would be.
Everything lwburk says is correct, however, the below does what you were trying to accomplish, it does this by calling an init() method from MyModule.
var MyModule = function(){
return this.init();
};
MyModule.prototype.init = function(){};
MyModule.RelatedModule = (function() { // add properties to the MyModule object
return function() {
console.log("ran RelatedModule");
};
}());
MyModule.prototype.init = function(){
console.log("ran MyModule");
};
var inst1 = new MyModule(),
inst2 = new MyModule.RelatedModule();
First, there is a known browser bug where the constructor property (of the constructed object) correctly resolves using the prototype, but is not applied in object construction. So you need the following polyfill:
function NEW(clas, ...args)
{
let res = Object.setPrototypeOf({}, clas.prototype);
res.constructor.apply(res, args);
return res;
}
Second, you need to be setting MyModule.prototype.constructor instead of MyModule.constructor. The reason is that MyModule.constructor is the function that constructs new classes, not the function that constructs new objects. (See: Why does a class have a "constructor" field in JavaScript?)
In other words:
var MyModule = {}; // create object first, try to set a constructor on it later
MyModule.RelatedModule = (function() { // add properties to the MyModule object
return function() {
console.log("ran RelatedModule");
}
}())
// set the `MyModule` prototype.constructor instance function and retain the `MyModule.RelatedModule` property
MyModule.prototype = {
constructor() {
console.log("ran MyModule");
}}
var inst1 = NEW(MyModule), // logs "ran MyModule"
inst2 = NEW(MyModule.RelatedModule); // logs "ran RelatedModule"
The short answer is that you can't do that. You can however change the prototype of an object. Check out this answer for insight into how to rethink your approach to work with this constraint: Changing constructor in JavaScript

Create a single object

I want to create a single object. Does the below code make sense?
singleObj = new function () {
// act as a constructor.
};
Am I hurting any good practice?
I need a constructor. A simple object literal would not be useful here.
If you want just a single object, in that you are never going to make one again, an object literal works perfectly here.
var x = { };
Will give you an object.
In order for
var F = function() {
};
to give you an object you will need to invoke F
var x = new F();
you could try someting like:
var objCreate = function() {
var obj = {};
// do constructor logic
return obj;
};
Just create a new object and then populate it. You don't need a contrustor to do this.
var singleObject = {};
singleObject.value1 = "whatever";
If you really want to use a function, then you need to actually call it.
var singleObj = new (function () {
// act as a constructor.
})();
We can use a self executing function by creating a anonymous function function(){}, and immediately calling it with an empty argument set.
http://www.w3schools.com/js/js_objects.asp
//Used to create an object
personObj=new Object();
personObj.firstname="John";
personObj.lastname="Doe";
personObj.age=50;
personObj.eyecolor="blue";
//Used as a constructor for the object
function person(firstname,lastname,age,eyecolor)
{
this.firstname=firstname;
this.lastname=lastname;
this.age=age;
this.eyecolor=eyecolor;
}
//how to declare objects via constructor template
var myFather=new person("John","Doe",50,"blue");
var myMother=new person("Sally","Rally",48,"green");

Categories

Resources