function filter_effect(effect_name){
var tmp_img = document.createElement("IMG");
tmp_img.src = get_cropped_image()
tmp_img.style.display = "none"
Caman(tmp_img, function (){
this[effect_name]();
this.render(function () {
change_picture(this.canvas.toDataURL("image/jpeg"))
});
});
}
this is my code and when I run this I get this error
Uncaught TypeError: this[effect_name] is not a function
Can anyone help that what I should do to fix this?
You should change your function call and pass the this. Change this line, it would be solved:
Caman.call(this, tmp_img, function (){
/* Your callback function body */
});
Here this means the filter_effect function. When you want to change the this object in function calls, you have to use .apply() or .call() to change it.
Here is a reference for this post.
You have to clarify 'this' reference value, it must be refer to a javascript object which effect_name property of which be declared as function, use browser's debugger to have scrutiny over it's value
Related
Can someone please explain why the function not getting the value of the object in the first way?
I got the Backbone.View:
var some.view = Backbone.View.extend({
elements = {},
//...
//some init, filling up elements...
//...
stopTask: function() {
// Calling the function with parameters explained later
stopThisTask(...);
}
});
And the function:
function stopThisTask(task){
console.log(task);
}
When I call stopThisTask in the following way, the task parameter is undefined
stopThisTask(this.elements);
However, when I do it like this, the task has the value
var tmp = this.elements;
stopThisTask(tmp);
Can someone please explain why is that?
If I know right the variables are passed by value, and the obects are passed by references. However, does that mean in some way I loose the reference for the elements object?
I'm suspecting that the this.elements gets resolved inside the stopThisTask function, so this will point to stopThisTask instead of to the caller of stopThisTask.
By explicitly setting the tmp parameter in the caller, you guarantee the correct this scope is used.
Should be equivalent to
stopThisTask.call(this, this.elements);
I am trying to create a basic javascript framework that you can pass different things into, including functions for it to execute later. Right now, I'm in a more simple testing phase, but I can't quite get the function calling to work. A piece of my code is here:
[My JS Fiddle][1]http://jsfiddle.net/mp243wm6/
My code has an object that holds different data, and I want to call the method later, but with data that is available at the time of creation. Here is a code snippet of the function that uses the function that is passed to the object:
clickMe : function() {
this.obj.click(function() {
this.func();
});
}
Any suggestions or things I should read are welcome.
The problem is that there're two different contexts:
clickMe : function() {
// here is one
this.obj.click(function() {
// here is another
this.func();
});
}
You can simple pass the function as parameter, like the following:
clickMe : function() {
this.obj.click($.proxy(this.func, this));
}
http://jsfiddle.net/mp243wm6/2/
The problem:
Considering your code in the JSFiddle, you have:
onClick : function() {
this.obj.click(function() {
this.func();
});
},
As noted, you have different contexts going on here.
Consider the snippet this.obj.click(function() { this.func(); }). The first this here is a reference to the framework.events object. The second this here is a reference to whatever will be this when this function get called. In the case of your JSFiddle, when this.func gets called, this is actually the DOM object that represents the <div id="test">TEST</div> node. Since it doesn't have a func function, calling func() on it causes:
Uncaught TypeError: undefined is not a function
You have to understand the following: you have to pass the correct this in which you want the function func to be called.
The solution:
A couple of ways to make it work as you would like:
1. with bind
this.obj.click(this.func.bind(this));
This way, you are telling: "call my this.func function, but make sure that it will be called using the this that I am passing as a parameter". Vanilla JS, no $.proxy stuff.
JSFiddle
2. with a copy of the reference to the actual function
onClick : function() {
var theFunctionReference = this.func;
this.obj.click(function() {
theFunctionReference();
});
},
This way, you will not rely on the value of this outside of the context of the framework.events object.
JSFiddle
The issue is that this is not bound to the correct object. I would suggest you look into Function.bind() because that creates a function with this pointing to the right thing.
I'm not sure if this has been asked before because I don't know what it's called.
But why wouldn't a method like this work? Below is just a general example
<script>
document.getElementById('main_div').onclick=clickie(argument1,argument2);
function clickie(parameter1,parameter2){
//code here
}
</script>
The code above would work fine if the event handler was assigned without parameters, but with parameters, it doesn't work. I think I read online that to overcome this problem, you could use closures. I'm assuming it's because of the parentheses ( ) that is calling the function immediately instead of assigning it to the event?
Because you're calling the function immediately and returning the result, not referencing it.
When adding the parenthesis you call the function and pass the result back to onclick
document.getElementById('main_div').onclick = clickie(); // returns undefined
so it's actually equal to writing
document.getElementById('main_div').onclick = undefined;
which is not what you want, you want
document.getElementById('main_div').onclick = clickie;
but then you can't pass arguments, so to do that you could use an anonymous function as well
document.getElementById('main_div').onclick = function() {
clickie(argument1,argument2);
}
or use bind
document.getElementById('main_div').onclick = yourFunc.bind(this, [argument1, argument2]);
It is however generally better to use addEventListener to attach event listeners, but the same principle applies, it's either (without arguments)
document.getElementById('main_div').addEventListener('click', clickie, false);
or bind or the anonymous function to pass arguments etc.
document.getElementById('main_div').addEventListener('click', function() {
clickie(argument1,argument2);
}, false);
The easiest way is:
yourElement.onclick = yourFunc.bind(this, [arg1, arg2]);
function yourFunc (args, event) {
// here you can work with you array of the arguments 'args'
}
When you say onClick = function() {...} you are registering your function with some internal JavaScript library. So when the "click" happens, that library invokes your function.
Now imagine you're the author of that library and someone registered their function with it. How would you know how many parameters to pass to the function? How would you know know what kind of parameters to pass in?
clickie(argument1,argument2)
This means to invoke the function and return its return value.
clickie
This simply is a reference to the function (doesn't invoke/execute it)
To bind an event to a element, you need to use either the attachEvent or addEventListener method. For example.
/* Non IE*/
document.getElementById('main_div').addEventListener('click', function () {}, false);
/* IE */
document.getElementById('main_div').attachEvent('onclick', function () {});
A function name followed by parentheses is interpreted as a function call or the start of a function declaration. The a onclick property needs to be set to a function object. A function declaration is a statement, and is not itself a function. It doesn't return a reference to the function. Instead it has the side effect of creating a variable in the global scope that refers to a new function object.
function clickie(param) { return true; }
creates a global variable named clickie that refers to a function object. One could then assign that object as an event handler like so: element.onclick = clickie;. An anonymous function declaration (often confused with a closure; for the difference see Closure vs Anonymous function (difference?)) does return a function object and can be assigned to a property as an event handler, as follows:
element.onclick = function(event) { return true; };
But this doesn't work:
element.onclick = function clickie(event) { return true;};
Why? Because function clickie(event) { return true;} is a statement, not a function. It doesn't return anything. So there is nothing to be assigned to the onclick property. Hope this helps.
I found in requirejs-text plugin weird code. So load method accepts onLoad callable which is invoked for a few times as onLoad(), but later there is error handler which checks for an error method.
if (onLoad.error) {
onLoad.error(err);
}
Am i missing something or it's obvious code issue?
You cannot use a normal object as a callable entity, but a function is a type of object, so you can add properties to a function.
var onLoad = function(){
};
onLoad.error = function(){
};
At the very beginning of the javascript file, I have:
var lbp = {};
lbp.defaults = {
minLength: 40
};
I can successfully alert it afterwards, with:
alert(lbp.defaults.minLength);
But as soon as I put it inside a function, when I alert, I get "Undefined". What gives, and how do I avoid this? Is it absolutely necessary to pass this variable into each function, for example, by doing:
function(lbp) { alert(lbp.defaults.minLength); }
I would have thought that defining it first, it would attain global scope and not be required to be passed in?
Thanks in advance for enlightening me :)
====================================
EDIT:
The problem seems like it might be my initialize function is itself defined within lbp. Is there any way to use this function var, and still use lbp vars inside it?
lbp.initialize = function() {
alert(lbp.defaults.minLength);
};
The full bit of code looks like this:
<script type="text/javascript">
var lbp = {
defaults: {
minLength: 40
}
};
lbp.initialize = function() {
alert(lbp.defaults.minLength);
};
window.onload = lbp.initialize;
</script>
Are you actually passing lbp as the argument? Otherwise the parameter with the same name will hide the global variable.
Use this.
var lbp = {
defaults: {
minLength: 40
}
};
lbp.initialize = function() {
alert(this.defaults.minLength);
};
window.onload = function() { lbp.initialize(); };
If you call initialize as a method of lbp, this will point to lbp. When you assign a function to an event handler, such as window.onload, you are essentially copying the body of that function to the object on which the event handler is defined. So,
window.onload = lbp.initialize
is the same as
window.onload = function() {
alert(this.defaults.minLength);
};
Now, this is pointing to window, which is obviously not what we want. By wrapping the call to lbp.initialize() in a function, we preserve the context of this within that function and we can make sure that it always points to lbp. Check out this for a more complete explanation.
This works for me from javascript console in Firefox:
javascript:var lbp={}; lbp.defaults={minLength: 40};function xx() { alert(lbp);alert(lbp.defaults);alert(lbp.defaults.minLength); }; xx();
Gives output [object Object], [object Object], 40.
So, it seems there might be some problem with some associated code, which is not shown?
In the original code where you are trying to use lbp in a function. You are passing lbp in as an argument. This would hide the lbp from the global scope with a local (to the function) variable of the same name (unless when calling the function you passed lbp in again).
//this is what you have and will not alert a thing other
//and will probably throw an error
function(lbp) { alert(lbp.defaults.minLength; }
//should just be this with no argument. this will allow
//the function to see lbp in the global scope.
function() { alert(lbp.defaults.minLength; }
by passing lbp as a parameter in the first function it is not seen inside the function as the global object, but the local argument.