jquery event function call with oop? - javascript

var objs = new Array();
function Foo(a) {
this.a = a
$("#test").append($("<button></button>").html("click").click(this.bar));
}
Foo.prototype.bar = function () {
alert(this.a);
}
$(document).ready(function () {
for (var i = 0; i < 5; i++) {
objs.push(new Foo(i));
}
});
is it possible to make it so that when a button is clicked,
it returns corresponding Foo.a value (from Foo obj that created the button)?

The #Khnle's answer is close, but with that approach you need an anonymous function to use the self reference:
function Foo(a) {
this.a = a;
var self = this;
$("#test").append($("<button></button>").html("click").click(function () {
self.bar(); // correct `this` value inside `bar`
}));
}
You can also use the $.proxy method, to preserve the object context:
function Foo(a) {
this.a = a
$("#test").append($("<button></button>")
.html("click")
.click($.proxy(this.bar, this)));
}
Check the above example here.

Inside your click handler, this no longer refers to the Foo object, but the element where click takes place, which is the button element in this case. So one way to fix it is as follow:
function Foo(a) {
this.a = a;
var self = this;
$("#test").append($("<button></button>").html("click").click(self.bar));
}

Here's more jQuery style (no global objs or Foos)
(function ($) {
$.fn.aghragbumgh = function (settings) {
var config = { 'a': 0 };
if (settings) $.extend(config, settings);
var bar = function () {
alert(config.a);
}
this.each(function () {
$(this).append($("<button></button>").html("click").click(bar));
});
return this;
};
})(jQuery);
$(document).ready(function () {
for (var i = 0; i < 5; i++) {
$('#test').aghragbumgh({ 'a': i });
};
});
Html:
<div id="test"></div>

Related

How to take value from function which is in another function, as argument of final function

So I have 3 functions.
What i want to achieve is to take value from one function which is nested in parent function, and the pass it as the argument in third function.
And can this be achieved with closer, and how ?
Thanks so much.
function foo () {
var rand = 10;
function bar() {
return {
age:rand;
}
}
}
function addValue(arg) {
console.log(bar());
}
Call as below
function foo () {
var rand = 10;
return function bar() {
return {
age:rand
}
}();
}
function addValue(arg) {
console.log(foo());
}
Edited
function foo (func) {
var rand = 10;
function bar() {
return {
age:rand
}
};
//Do your stuff
return eval(func+"()");
}
function addValue(arg) {
console.log(foo("bar"));
}
You can instead assign the function to the parent object and call it like this.
function foo(){
var rand = 10;
this.bar = function(){
return {age: rand};
}
}
var obj = new foo();
function addVal() {
console.log(obj.bar());
}
addVal();

A prototype-less, new-less, one-instance-only javascript object?

This doesn't work.
var genericClickHandler = function () {
this.handlers = [];
if (console && console.log) {
console.log("this:", this);
console.log("event:", event);
}
};
genericClickHandler.addHandler = function (handlerSpec) {
this.handlers.push(handlerSpec);
return this;
};
genericClickHandler.executeHandler = function (handlerName) {
for (var i = 0; i < this.handlers.length; i++) {
if (handlerName === this.handlers[i][0]) {
this.handlers[i][1]();
}
}
return this;
};
It doesn't work because the addHandler can't see the this.handlers in genericClickHandler.
Anyway what I'm after is function that gets defined once, but has methods and properties. I want to be able to use the function with Google Maps like this:
heatmap.addListener("click", genericClickHandler)
circle.addListener("click", genericClickHandler)
polygons.addListener("click", genericClickHandler)
So in the first instance, it only reports the this and event object. However, I then want to write code which extends the genericClickHandler dynamically so that it can implement map-object-specific behaviour.
Here's an example of what I meant using an object rather than a function.
var genericClickHandler = {
handlers: []
};
genericClickHandler.addHandler = function (name, fn) {
this.handlers.push([name, fn]);
return this;
};
genericClickHandler.executeHandler = function (name) {
for (var i = 0, l = this.handlers.length; i < l; i++) {
if (this.handlers[i][0] === name) this.handlers[i][1]();
}
};
genericClickHandler.addHandler('click', function () {
console.log('hi');
});
genericClickHandler.addHandler('click', function () {
console.log('hallo again');
});
genericClickHandler.executeHandler('click'); // hi... hallo again
DEMO
if you want to create an object, here you can see 2 ways to do the same thing, javascript got multiple way to write the same things.
var genericClickHandler = function()
{
this.handlers = [];
this.addHandler = function (handlerSpec)
{
this.handlers.push(handlerSpec);
return this;
},
this.executeHandler = function (handlerName)
{
this.handlers[handlerName]();
return this;
}
};
//sample:
var tmp = new genericClickHandler();
console.log(tmp.handlers);
console.log(tmp.addHandler("TEST"));
Another way to write the same object, but more optimised : prototype will be stored once for each object
var genericClickHandler = function(){}
genericClickHandler.prototype =
{
handlers:[],
addHandler : function (handlerSpec)
{
this.handlers.push(handlerSpec);
return this;
},
executeHandler : function (handlerName)
{
this.handlers[handlerName]();
return this;
}
}
//sample:
var tmp = new genericClickHandler();
console.log(tmp.handlers);
console.log(tmp.addHandler("TEST"));

Try to create object of returned function?

I was trying something different and ended up with these codes..
var f1 = function() {
this.x = 10;
this.innerf = function() { console.log(this.x); }
}
var of1 = new f1();
of1.innerf();
var f2 = function() {
return function() {
this.x = 10;
this.innerf = function() { console.log(this.x); }
}
}
var of2 = new f2();
of2.innerf();
It is throwing error ??! of2.inner is not a function
So, my anonymous function is returning same function body to my variable.
Why still i cannot able to instantiate??
The first part returns an object of which you can call the innerf method.
The second part returns a function that would return an object if you called it. But you don't.
This would work. Call the function f2(). It's return value is the anonymous function. Then, with new <return value of f2>(), you can create an instance of the object.
var f2 = function() {
return function() {
this.x = 10;
this.innerf = function() { console.log(this.x); }
}
}
var of2 = new (f2())();
of2.innerf();
// The two lines above can also be written as:
var of3constructor = f2(); // This returns the inner anonymous function.
var of3 = new of3constructor(); // This creates an instance by invoking the anonymous function.
of3.innerf();
Examples that work:
Creating it directly:
var f1 = function() {
this.x = 11;
this.innerf = function() {
console.log(this.x);
}
}
var of1 = new f1();
of1.innerf();
Returning a new object from a function:
var f2 = function() {
return new function() {
this.x = 12;
this.innerf = function() {
console.log(this.x);
}
}
}
var of2 = f2();
of2.innerf();
Returning an object:
var f3 = function() {
return {
x: 13,
innerf : function() {
console.log(this.x);
}
}
}
var of3 = f3();
of3.innerf();
Another one:
var f4 = function() {
return function() {
this.x = 10;
this.innerf = function() {
console.log(this.x);
}
}
}
var of4 = new (f2())();
of2.innerf();
Remember that when you call a function without the "new" keyword "this" points object where the functions was declared, in this case "window"
You need to return this from the inner function to the outer function. Also you need to run the inner function immediately.
jsFiddle:
http://jsfiddle.net/5dxybbb5/
var f1 = function() {
this.x = 10;
this.innerf = function() {console.log(this.x);}
}
var of1 = new f1();
of1.innerf();
var f2 = function() {
return function() {
this.x = 10;
this.innerf = function() {console.log(this.x);}
return this;
}();
}
var of2 = new f2();
of2.innerf();
Also this explains the () after a function declaration
What is the (function() { } )() construct in JavaScript?

'this' is unequal to Bar in prototype

In the following code snippet, 'this.x()' can only be called in case 2 (see main()).
Also Bar unequals this in case 1, but is equal for case 2.
function Class_Bar() {
this.panel = null;
this.init = function () {
// do some stuff
this.panel = 20;
}
this.apply = function () {
alert(Bar == this);
Bar.x();
this.x();
}
this.x = function() {
alert("Some friendly message");
alert(Bar.panel);
}
}
var Bar = new Class_Bar();
function Class_Factory() {
this.factories = new Array();
this.add = function (init, apply) {
this.factories.push({"init":init, "apply":apply});
}
this.init = function () {
for (var i = 0; i < this.factories.length; ++i) {
this.factories[i]["init"]();
}
}
this.apply = function () {
for (var i = 0; i < this.factories.length; ++i) {
this.factories[i]["apply"]();
}
}
}
var Factory = new Class_Factory();
function main() {
// Case 1
Factory.add(Bar.init, Bar.apply);
Factory.init();
Factory.apply();
// Case 2
Bar.init();
Bar.apply();
}
main();
http://pastebin.com/fpjPNphx
Any ideas how to "fix" / workaround this behaviour?
I found a possible solution, but it seems to be a "bad" hack.: Javascript: How to access object member from event callback function
By passing Bar.init, you're really only passing the function but not the information that it belongs to Bar (i.e. what the this value should be). What you can do is binding that information:
Factory.add(Bar.init.bind(Bar), Bar.apply.bind(Bar));

Javascript: Member-variable-accessing closures

I'm wondering how to deal with member variables in closures in JavaScript. The following code alerts "6".
function testy()
{
function blah()
{
this.a = 5;
this.func = function()
{
this.a = 6;
alert(this.a);
}
}
var x = new blah;
x.func();
}
but this code alerts 5.
function testy()
{
function execute(func)
{
func();
}
function blah()
{
this.a = 5;
this.func = function()
{
execute(function()
{
this.a = 6;
});
alert(this.a);
}
}
var x = new blah;
x.func();
}
How do I pass a closure which still accesses the member variables of the enclosing object?
execute(function()
{
this.a = 6;
});
function execute(func)
{
func();
}
Your calling the function as func(); and by default without specifying a context this will resolve to the global context which is window in the browser.. There are three options you can use here.
make this local
var that = this;
execute(function()
{
that.a = 6;
});
Now that points to the correct this.
bind this scope to the function
execute((function()
{
this.a = 6;
}).bind(this));
This will bind the correct / expected this scope to your function. Note that Function.prototype.bind is ES5 and will break older browsers. _.bind is a reasonable cross browser alternative.
edit execute
function execute(f, context) {
f.call(context);
}
execute(function() {
this.a = 6;
}, this);
Your passing the context as an extra parameter to execute. Then execute will call Function.prototype.call to make sure that the function is called with the desired context
Try this:
function blah()
{
this.a = 5;
this.func = function()
{
var self = this;
execute(function()
{
self.a = 6;
});
alert(this.a);
}
}

Categories