I have a reference to a DOM element. I know I can add a function to it as in the following example where the function foo is added:
<div id="myDiv"></div>
<script>
function bar() {
console.log("inside bar");
}
var myDiv = document.getElementById("myDiv");
myDiv.foo = function () {
bar();
}
myDiv.foo();
</script>
Invoking myDiv.foo() executes the document-level function bar() as expected.
What I would like to know: is it possible to add the document-level function bar as a member of myVar? So that I can call myDiv.bar() directly? The key is that bar would have to be able to access members of myDiv using the key word "this". I'm aware I could change bar to accept myDiv as a parameter and access its members that way, but I'm really interested to know if the specific approach I am asking about is possible. Thanks.
You just assign the function instead of creating a new one.
myDiv.foo = bar;
myDiv.foo();
Related
today my question is asking how I would access a function inside a function. So, for example, I have a button, and if I click it, it would alert. The thing is, if you have a function surrounding the function, the inside function with the alert would not alert.
Here's an example:
html:
<button onclick="doStuff()">Alert</button>
js:
function nothing() {
var doStuff = function() {
alert("This worked!")
}
}
so the doStuff() function would not work. Can someone help me find a way to access it?
#Joseph the Dreamer is ultimately correct, but if you were dead set on calling a function that's nested in another function you could use an OOP approach.
Create a javascript "class" object and scope your function to "this":
function Nothing() {
this.doStuff = function() {
alert("works");
}
}
Next you add an id to your button,
along with a click event listener
Then, inside your click event you can call doStuff within the Nothing "Class" function like this:
var object = new Nothing();
object.doStuff();
https://jsfiddle.net/me7fek5f/
You can't. That's because it's enclosed in a scope that you can't really access globally. The only way you can access it is to expose it somewhere outside nothing.
Is this a homework question?
You're probably asked to do something like this:
function nothing() {
var doStuff = function() {
alert("This worked!")
}
var yourButton = getYourButton();
attachClickListener(yourButton, doStuff);
The implementations of getYourButton and attachClickListener are left to the reader.
Having the following html:
<div id="plugin">
<script>
(function(){
this.do = function(e){
alert("cool!");
};
});
<script>
<div>
how do I call this.do (say from a parent element click button event handler)?
Maybe some more information will help advising on the right solution. It's a plugin, I want both markup and script to be part of the same file. I also want to be able to do something like:
$("#plugin").*controller*.do(); from outside of the plugin.
Here's a candidate solution, inspired by Scott's answer:
<div>
(function(){
var plugin = $("#plugin");
plugin.do = function(e){ alert("cool!"); };
});
</div>
then from outside:
$("#plugin").do();
any issues with it?
This looks like you can't, as the wrapper function doesn't have a name and does not self-execute. So the code never runs. If it would run, the this keyword in a global function refers to the window object and the inner function would be globally available.
(function(){
this.do = function(e){
alert("cool!");
};
})(); // <-- additional parentheses to self-execute the wrapper function
window.do === do; // true
// use
do();
// or
window.do();
// to call the inner function
But having such a wrapper function looks like you want to avoid global functions and variables (which is good for a number of well documented reasons). In that case you could define do as private method of your module and refer to it inside the wrapper function.
(function(){
var do = function(e){
alert("cool!");
};
var button = document.querySelector( 'button' ); // get the first button element
button.addEventListener( 'click', do, false );
})();
typeof do === 'undefined' // true; the function do is only available inside the wrapper function.
why are you against just doing?
<script>
function do(){
alert('cool!');
}
<script>
you could do :
<script>
window.do = function(){
...
}
</script>
then some where else:
window.do()
You can't. The outer function expression isn't called or assigned anywhere, so it will be discarded without ever evaluating the inner function expression.
If you want to bind the function somewhere, call addEventListener on the element you want to assign it to and pass it as the second argument.
I have a function localised to the main function and i want to use this to call it but it doesn't seem to work.
My code has:
function option(room,slot){
var div_id = document.getElementById(room);
var opacity = window.getComputedStyle(div_id).opacity
transition_opacity(div_id,opacity,0,function(){this.load});
function load(){
console.log('test'); //does not happen
}
}
Have i misunderstood the use of this or is the scope lost when i use function(){} to call load?
From your code it is not obvious, what object this could refer to. It depends on how option is called. However, if you define the load function inside of the option function anyway, it is best to just reference it directly. You will have to move the declaration of test above the transition_opacity call though:
function option(room,slot){
var div_id = document.getElementById(room);
var opacity = window.getComputedStyle(div_id).opacity;
function load() {
console.log('test');
}
transition_opacity(div_id,opacity,0,load);
}
As you can see, I just reference load directly. You could make another function which calls the load function inside (i.e. function() { load(); } – note the parentheses which calls the function) but that would give you no benefit but would just add another unneeded function to the stack. So just refer to the actual function itself.
For more information on the this keyword, check out this question. Spoiler: It’s more complicated than you would expect.
The scope of this is lost in this instance, probably pointing to the document. You can capture this to a variable in the outer scope to make this work as intended.
var context = this;
transition_opacity(div_id,opacity,0,function(){context.load();})
The above will not work however. This is because load does not exist on the context of this. You would need to define the load function as such:
context.load = function(){
console.log('test');
}
Both.
First, your load function is not a member/property of any this, the way you have it coded. Your load function is simply a nested function that exists within your option function, as has been sort of implicitly noted in other responses.
In your option function, if you want 'load' to become a member of 'this', you'd need to say so, like this:
function option(){
this.load = function(){}; // now load is actually a property of whatever this is
}
Second, you and the other poster are correct that 'this' is no longer the same 'this' by the time your anonymous function is called.
Whenever you call a function, a brand new 'this' is created and exists within the scope of that function. If you just call a function like this:
transition_opacity(args);
.. then within transition_opacity, 'this' just refers to the window object, or maybe window.document. For 'this' to refer to anything other than window or window.document, you need to (in effect) do one of the following:
myObject.transition_opacity(args);
transition_opacity.call(myObject, arg1, arg2, ..);
transition_opacity.apply(myObject, argArray);
or
var myObject = new transition_opacity(args);
In each of those cases, within transition_opacity, 'this' refers to myObject (or, well, in the last case, it refers to a new object that is being created and assigned to myObject).
Here is a way to do what it looks like you're trying to do:
var MyNamespace = {
option: function(room,slot){
var div_id = document.getElementById(room);
var opacity = window.getComputedStyle(div_id).opacity;
var _this = this;
transition_opacity(div_id,opacity,0,function(){
// Careful! Inside here, 'this' is just window or window.document,
// unless transition_opacity sets it to something using call or apply,
// in which case that 'this' is probably not the 'this' you want.
// So carefully refer to the saved instance of 'this':
_this.load();
});
},
load: function(){
console.log('test'); // now it should happen
}
}
.
.
MyNamespace.option(room, slot); // inside option, 'this' is MyNamespace.
Here's another way to do it:
function MyClass(){};
MyClass.prototype = {
// all the same stuff that is in MyNamespace above..
};
.
.
var myObject = new MyClass();
myObject.option(room, slot);
Clear as mud?
Just use
transition_opacity(div_id,opacity,0,load);
You have defined a 'load' within another function as an 'Function Declaration', so now it is only accessible within 'option' function and in other functions defined in this one by name 'load'. You can't access it by using 'this.load' no matter what 'this' is. If you want to access 'load' function as 'this.load' you can try this example to understand how 'this' keywoard works
// Function Declaration
function f1(callback){
callback();
};
// Function Declaration
function f2(){
// Function Expression
this.load = function(){
console.log("test");
};
f1(this.load);
};
var obj = new f2(); // test, this == obj, so obj.load() now exists
obj.load(); //test, this == obj
f2(); //test, this == window, so window.load() now exists
load(); //test, window is the global scope
Umm i didnt knew a better title,
I wonder if there is a way to do sth. like this:
function myFunc() {
//do some Stuff...
this.myMethod = function(x) {
//do some more Stuff
var nameofthevariable = myVar//somehow get the Variables name
myVar.somePropertie = "SomeOtherStuff";
}
}
myVar = new myFunc();
myVar.myMethod(x)
Is there a way to get the Name or the Var itself from inside the function, which instance it holds ?
So i can put back the Data, the method creates into the variable, without passing it as argument to the function or method =)
Thanks for any answers
Answer
Thanks for the Answer =), ah thats sad
The Problem with thisis that I have an Object,
a Propertie of the Object creates an Instance of myFunc and executes myMethod()
this should add a new Propertie to myObj, so i have the Output from myMethod seperated from the instance of myFunc()
function myFunc() {
//do some Stuff...
this.myMethod = function(x) {
//do some more Stuff
var nameofthevariable = myObj//somehow get the Variables name
myObj.somePropertie = "SomeOtherStuff";
//and here i could do
this.Parent.somePropertie = "SomeOtherStuff";
}
}
myObj = {}
myObj.myProp = new myFunc();
//i could do:
myObj.myProp.Parent = myObj
//
myObj.myProp.myMethod(x)
But then i could pass myObj, as an Parameter to the myMethod too
I wanted to go Up to the Object i want to add sth, twice with the getting of the Variable Name,
I think, thiswon't work in that context, as i cant access variables of an level higher than the instance of myFunction
Your Edit
Oh yes, thanks =) in the real Code its a 'privileged' function and i can call the method,
I'll edit it in the Question,
Thanks for pointing that out, i didnt even realize that when writing this in the question here.
It works well except that i dont find a way, dynamically putting back the Data to the Object which holds the Instance"
You can't get the name of the variable, but you seem to be asking how myMethod() can add a property to myVar where myVar is the instance of myFunc that myMethod() was called on - in which case using this will work:
function myFunc() {
//do some Stuff...
this.myMethod = function(x) {
//do some more Stuff
this.somePropertie = "SomeOtherStuff";
}
}
myVar = new myFunc();
myVar.myMethod(x)
Note that the way you had defined myMethod() it was a private function accessible only from within myFunc() - to call it with the myVar.myMethod() syntax you need to make it a property (so I've changed that bit too).
The value of this within a function depends how the function was called. When you call myFunc() with the new operator JS sets this to the newly created instance. When you call a method with the myVar.myMethod() "dot" syntax JS sets this to myVar.
For more information about this I'd suggest reading the MDN this article.
I am using a plugin JS and need to call a function in it.
It is having functions inside a variable like,
var win = window;
var Page = function(pageOptions, callback) {
function abc(){
--------
}
function xyz(){
------
}
};
win.Sales = {
Page: Page
};
Now, I need to call a function abc(). How can I call it.
Already tried with win.Sales.page.abc();.
Please help me out on this. Thanks in advance.
You cannot do that with your configuration because the functions are local or private.
You should make them accessible globally like:
var Page = function(...) {
...
};
Page.abc = function() {
...
};
That way, abc is a property of Page, and you can then access it like Page.abc and execute it like Page.abc(). Functions are basically also objects so they can have properties too.
You cant call function abc since it is declared as a private member of the function referenced by variable Page.
If you want to call the function You have to make it as a property of the variable Page.
var Page = function(){
.........
.........
.........
}
Page.abc = function(){
}
But there is another problem of variable scoping like if there is another variable x defined in function Page and used inside function abc, it will not work.
Anyway since you've said it is a js plugin I do not think it will be possible for you to change the function Page. So the answer will be No you cannot do that.