How to access base object from inside method Javascript - javascript

I've written a class and this is a snippet taken from it to demonstrate my problem.
<!--language:lang-js-->
var myclass = function () {
this.addItem = function () {
//generateDiv and append..
//generatedeletebtn and append
btn.onclick = this.deleteItem;
}
this.deleteItem = function () {
console.log(this);
}
}
Inside the deleteItem function, this represents the HTML element clicked. Is there a way I can access the myclass object directly?
I've tried changing
div.onclick = this.deleteItem
to
div.onclick = this.deleteItem(this) which works as far as accessing the object but the parenthesis invoke the function and remove the items as soon as they're added so that's no good.

This looks like a job for bind
btn.onclick = this.deleteItem.bind(this);
You can think of bind as wrapping function A referenced by this.deleteItem in another function B, which always invokes A with the context given as the first parameter of bind.
There is a polyfill available on MDN if you can't assume bind is available in your environment.

You can use the closure to store a reference to the myclass object itself in a variable called that. Then, when deleteItem is eventually called, it should use the myclass object as that.
var myclass = function () {
var that = this;
this.deleteItem = function () {
console.log(that);
}
}
You shouldn't have to worry about polyfills with this one.

Related

How to prevent "this" from being rebound by event handlers

I've got a JS object, and one of it's prototype functions is an event handler for a click. When that function gets called, the this object is set to the element that the click is bound to. I'd like this to be the instance of the object that the function belongs to. Is this possible, and if so, how do I do it? Solutions with or without jQuery are acceptable to me, although I'm sure that the rest of SO would appreciate a pure JS solution.
I've tried binding the function to this, and it gets bound to the window rather than the instance of the object.
Example of what I want: In this demo (code duplicated below), I want an alert that says "Bark" when the button is clicked.
var Dog = function () {
this.sound = "Bark";
}
Dog.prototype = {
sayHello: function (e) {
if (typeof this.sound == "undefined") {
alert("I don't know what sound I should make!\n" + this);
} else {
alert(this.sound);
}
}
}
var d = new Dog();
var elem = document.getElementById("click");
elem.addEventListener("click", d.sayHello);
You can use .bind() like this:
elem.addEventListener("click", d.sayHello.bind(d));
The manual way of doing it is with your own function:
elem.addEventListener("click", function(e) {
return d.sayHello();
});
If you always intend for a function to be invoked with its own context, do the binding when the constructor runs instead:
var Dog = function () {
this.sound = "Bark";
this.sayHello = this.sayHello.bind(this);
}
http://jsfiddle.net/04ykpsx1/1/
Something like _.bindAll can reduce the boilerplate for you.
This is a better approach than forcing your callers to always call a function with .bind, because they shouldn't need to understand your class so deeply.

How to call current objects public method in JavaScript?

At the moment I came this far.
function Class() {
var privateMethod = function () {
return 'private'
}
this.publicMethod = function () {
return 'public'
}
var _constructor = function () {
$(document).on('click', _onClick)
}
var _onClick = function () {
// My error is `this`, focus now on the click event, but I need the object itself
console.log(privateMethod())
console.log(this.publicMethod())
}
_constructor()
}
$(document).ready(init)
function init() {
new Class()
}
The problem is that, in the click event, I am unable to call publicMethod.
I am able to call the private method.
How can I achieve this?
The problem is that, in your handler you've lost your context (this no longer means your instance of Class, it instead means the object that triggered your event. You need to create a closure scoped version of this to hold onto that context.
var self = this;
var _onClick = function () {
// My error is `this`, focus now on the click event, but I need the object itself
console.log(privateMethod())
console.log(self.publicMethod())
}
You have a scope issue, this in the onclick is pointing to a different object than what you expect. In your case it is the document
var that = this;
var _onClick = function () {
// My error is `this`, focus now on the click event, but I need the object itself
console.log(privateMethod())
console.log(that.publicMethod())
}
Running Example

Why I cannot access variable through this in Windows 8 JavaScript App

My code is very simple. Ans to me it should work.
var preview = WinJS.Class.define(
function (el, options) {
el.winControl = this;
this.el = el;
this.textarea = d.getElementById('preview-input');
this.preview = d.getElementById('preview-text');
this.form = d.getElementById('perview-form');
this.preview.addEventListener('click', this.click, false);
//WinJS.Utilities.query("button", this.form)
//this.preview.addEventListener('', this.save, false);
},
{
click: function (e) {
this.form.style('display', 'block');
}
}
);
WinJS.Namespace.define('RegCtrl', { preview: preview });
But when click occurs this.form seems to be undefined of null. Why? I do not want to initialize objects in every method of the class.
New tests
I made additional test very small
var preview = WinJS.Class.define(
function (el, options) {
var test = 1;
this.test = 1;
this.test1();
},
{
test1: function () {
console.log(this.form, test);
}
}
);
WinJS.Namespace.define('RegCtrl', { preview: preview });
This test fails on line this.test1();. What I think now that this class is called RegCtrl.preview() rather than new RegCtrl.preview().
How do I shek inside the function that this called as new but not a simple function?
The other answers aren't explaining what's going on, and as such are giving incorrect advice.
JavaScript has first-class function objects - you can pass them around as values. That's exactly what you're doing when you set up this callback:
this.preview.addEventListener('click', this.click, false);
You're taking the contents of the this.click property, which happens to be a function, and handing it to the addEventListener function to do whatever it wants with it.
I was very specific about terminology there - note I specifically said function, not method. JavaScript doesn't really have a method construct, it just has methods as properties on an object.
So where does the "this" member come from? It's determined at the caller - the object you use on the left side of the '.' is the one that becomes the value of this. For example,
function exampleFunc() { console.log("this.myName = " + this.myName); }
var a = { myName: "Chris", doSomething: exampleFunc };
var b = { myName: "Bob", doSomething: exampleFunc };
Note I've assigned the exact same function to the doSomething properties. What what happens:
a.doSomething(); // Outputs "this.myName = Chris"
b.doSomething(); // Outputs "this.myName = Bob"
The exact same function object, called through two different objects, has a different this pointer.
exampleFunc is a global function, let's call it:
exampleFunc() // Outputs "this.myName = undefined"
So where'd the undefined come from? In a global function, "this" is set to window (the global scope), which didn't have the myName property defined. Which also means that you could do this instead:
myName = "Global Name"; // note, no var - we want this global
exampleFunc(); // Outputs "this.myName = Global Name"
Ok, so what's going on with the original question? Basically, you've passed the function this.click to be the callback, but you haven't passed the "this" pointer that you want it called through. Actually, addEventListener doesn't have a way to pass the this pointer. As a result, when the function is invoked this is not pointing at your object. I don't remember off the top of my head what it's pointing at - it's either window or the element that was clicked on, check the DOM documentation to verify.
To get it to call the right function with the right context (context = the correct "this"), the traditional approach is to use a closure. Capture "this" in a variable, then pass in an anonymous function that calls your actual callback with the right this pointer. The code looks like this:
var preview = WinJS.Class.define(
function (el, options) {
// Capture your current this pointer in a global variable
// Using "that" as the name comes from JavaScript: The Good Parts book
var that = this;
el.winControl = this;
this.el = el;
this.textarea = d.getElementById('preview-input');
this.preview = d.getElementById('preview-text');
this.form = d.getElementById('perview-form');
// Note what gets passed instead of this.click:
this.preview.addEventListener('click',
function (e) {
// NOTE: Calling through "that": "this" isn't pointing to the right object anymore
// Calling through "that" resets "this" inside the call to click
that.click(e);
}, false);
},
{
click: function (e) {
this.form.style('display', 'block');
}
}
);
This is a common enough pattern that ECMAScript 5 has a utility function to build these wrappers for you - function.bind. Do this:
this.preview.addEventListener('click',
this.click.bind(this),
false);
The construct this.click.bind(this) will construct a new function that, when called, will set the "this" reference to whatever you passed (in this case "this"), and then invoke the function you called it on.
Yes, there are a lot of different values for "this" floating around. Keeping track of what "this" is pointing at is an important part of mastering JavaScript programming.
I think you may want to define a global JavaScript variable as :
var myForm = document.getElementById('perview-form');
or jest define var myForm; and initialize inside function (el, options) as:
myForm = d.getElementById('perview-form');
Now you can use this variable in your function as :
myForm.style('display', 'block');
EDIT: I believe you may define this variable as first line in your WinJS.Class.define to make it instance level variable as below:
var preview = WinJS.Class.define(
var myForm;
function (el, options) {
....
....
myForm = d.getElementById('perview-form');
...
},
{
click: function (e) {
myForm.style('display', 'block');
}
});
This is a really hard thing to research if you don't know what to look for. I added one line and changed another line. That should fix your issue.
In short, the keyword this gets reset every time you enter a new function, this the value of this inside your click function is not the same this of the outer scope. Preserve this this you want. The name of that seems fairly common.
Edited based on the link provided by the OP.
This code is UNTESTED. If using this doesn't work now, then I'd try this2
Sorry I can't test this, but I don't have the framework anywhere so I'm doing
educated guesswork.
var preview = WinJS.Class.define(
function (el, options) {
that = this; // No var should be needed since it is declared already
el.winControl = this;
this.el = el;
this.textarea = d.getElementById('preview-input');
this.preview = d.getElementById('preview-text');
this.form = d.getElementById('perview-form');
this.preview.addEventListener('click', this.click, false);
//WinJS.Utilities.query("button", this.form)
//this.preview.addEventListener('', this.save, false);
},
// This is the section for instance vars
{
click: function (e) {
that.form.style('display', 'block'); // AND THIS ONE
},
that: null // Added instance variable
},
// And these are static variables
{
that2: null
}
);

How to change function inside constructor in JavaScript?

I need to edit the function which locates inside of the constructor.
Example:
some.thing = function() {
this.somefn = function() { // this is the function that I need to fix
...
}
}
But function should be edited not just only for a single object (new obj = some.thing();) but also for any created objects by this constructor.
So is there any way to edit such inner-functions?
Here is a solution based on prototype:
var Something = function () {
this.f = function () {
console.log("Something");
};
};
var Old = Something;
var Something = function () {
Old.apply(this);
this.f = function () {
console.log("New");
};
};
Something.prototype = new Old();
var s = new Something();
s.f(); // prints "New"
The solutions seem just a little too obvious, so I'm wondering if the trouble is that you don't have access to the original code, and you need a more dynamic solution.
If so, one option may be to override the constructor with your own constructor, and have it call the original, and then update the object.
Original code:
some.thing = function() {
this.somefn = function() { // this is the function that I need to fix
...
}
}
Your code:
// cache a reference to the original constructor
var _thing = some.thing;
// your constructor
some.thing = function() {
// invoke the original constructor on the new object.
_thing.apply(this, arguments);
this.somefn = function() { /*your updated function*/ };
};
// maintain inheritance
some.thing.prototype = Object.create(some.thing.prototype);
// make an instance
var theThing = new some.thing();
Now you're getting the benefit of the original constructor and prototype chain, but you're injecting your own function on to the objects being created.
Only trouble may be that the original function you replaced could make special use of the original constructor's variable scope. If that's the case, there would be an issue to resolve.
It would be possible to retain and invoke the original method that you overwrote before invoking yours. Not sure if this situation calls for that or not.
I exactly know your need cause last week I passed through it. I just implemented a complete inheritance model in javascript and as far as I remember, I had a problem with overriding constructors and calling the parent class's ctor when child class is initializing.
So I just solved the problem with modifing some points in my design and it's now working like a charm! (something like C# but in Javascript)
By the way, I don't suggest you to change a method contents this way, but here is a way to do that (I myself did not do that this way and AGIAIN I DO NOT RECOMMEND IT. THERE ARE MANY OTHER WAYS, BUT THIS IS THE EASIEST):
var test = function() { /*InjectionPlace*/ };
eval("var newTest = " + test.toString().replace(
"/*InjectionPlace*/",
"var i = 10; alert(i);"
));
test();
newTest();
Cheers

this keyword is window object within a constructor function

Ok, so I thought I understood this (no pun intended), but apparently not.
var Constructor = function () {
var internalFunction = function () {
return this === window;
};
this.myMethod = function () {
alert(internalFunction());
};
};
var myObj = new Constructor();
myObj.myMethod();
This alerts true. Why can't the internal function see this as the object? Instead I have to use alert(internalFunction.call(this)); in myMethod.
Edit: I was looking for an explanation as to why this is assigned in that way, not workarounds such as var self = this;, etc. Sorry if I didn't make that clear.
this is not bound until the function is called and is dependent on how the function is called. You could think of it as an extra parameter implicitly passed to the function.
In this case, the problem is that you're calling internalFunction using internalFunction(). The this value is set either by calling a function as a method (as in foo.bar() or foo["bar"]()) or by setting this explictly via call() or apply(). Your call is doing neither so this reverts to the global object.
The simplest way to achieve what you want in this case while keeping internalFunction private is to store a reference to this inside the constructor function:
var Constructor = function() {
var thisObj = this;
var internalFunction = function () {
return thisObj === window;
};
thisObj.myMethod = function () {
alert(internalFunction());
};
}
Because of functional scoping rules, this is reassigned inside each function... I would store a copy of your object as self and use it accordingly...
var Constructor = function () {
var self = this;
var internalFunction = function () {
return self === window;
};
this.myMethod = function () {
alert(internalFunction());
};
};
var myObj = new Constructor();
myObj.myMethod();
Should give you the output you expect.
SIDENOTE
This is a fairly precarious practice that javascript has created, mainly because if you forget the new keyword when using Constructor, you will get this referring to the window (god) object so you'll be attaching myMethod to the window without warning.
There are five ways to call a function in JavaScript. The value of this depends on which you choose:
Global function call (e.g. myFunction()). No explicit value for this is given. The value of this will be the default object (window in a browser).
Method call (e.g. obj.myFunction()). The value of this is the object on which the method was invoked (obj in this case).
Using the call method (e.g. myFunction.call(obj)). The value of this is provided explicitly (in this case obj).
Using the apply method (e.g. myFunction.apply(obj)). The value of this is provided explicitly (in this case obj).
Constructor function (e.g. new MyFunction()). The value of this is a newly-created object provided by the runtime.
Each of the five is explained in more detail here:
http://devlicio.us/blogs/sergio_pereira/archive/2009/02/09/javascript-5-ways-to-call-a-function.aspx
Its a scope issue try something like:
var Constructor = function () {
var $this = this;
var internalFunction = function () {
return $this === window;
};
this.myMethod = function () {
alert(internalFunction());
};
};
var myObj = new Constructor();
myObj.myMethod();

Categories