Calling method of object - javascript

I have the following object:
​var x = {
y: '33',
z: '88',
m: function() {
alert('this is the m element');
}
};
x.newObject = function() {
alert('mm');
function click(myval) {
alert('you have select the click function' + myval);
}
};
x.newObject.click('clickme'); ​​​​​​​​​// This is what I have tried; it's not working.
How can I call the click function of newObject?
jsFiddle

In the way you are coding it, you can't access click function since it's within another function.
If you insist coding it this way, have a call to newObject (which is a function) return click in an object so that it can be accessible. It's usually called function call "chaining", where the previous call returns an object that the next call can then use:
x.newObject = function(){
alert('monmon') ;
return {
click : function (myval){
alert('you have select the click function' + myval) ;
}
}
}
//a call to newObject returns an object with a click function
x.newObject().click('clickme')

This worked:
var x = {
y: '33',
z: '88',
m: function() {
alert('this is the m element');
}
}
x.newObject = new function() {
return {
click: function(myval) {
alert('you have select the click function' + myval);
}
}
}
x.newObject.click('clickme');​

click is scoped inside newObject, so it's not available anywhere outside of newObject. Are you trying to create an object with methods? If so, add it to the prototype:
newObject = function() { ... };
newObject.prototype = {
click: function(myval){ .. }
};
//now you can call newObject.click()
or you can have newObject return the methods you want to expose:
newObject = function(){
return {
click: function(myval){ ...}
}
};

Short answer: no way. Long answer: 'click' is treated somewhat like a local variable inside your bigger function, you cannot access local variables outside of function where they were declared. You need to assign your 'click' function to some globally accessed property or variable.

Maybe newObject shouldn't be a function, but an object. The following code works for me
var x = {
y: '33',
z: '88',
m: function() {
alert('this is the m element');
}
}
x.newObject = {
click: function(myval) {
alert('you have select the click function' + myval);
}
}
x.newObject.click();​

Related

Issue with click eventListener

I found an example task to display an alert on a page when you click anywhere in a document. In the task you need to edit only the display() function, which has two parameters - myFunc and myObj, so that the name of the person object is displayed. I've come up with something like this, but the alert only comes up after the page refreshes, not after each click on the document.
function start() {
var person = {
        name : "John"
    };
    function alertName() {
        alert(""+this.name.toUpperCase() + "");
    }
    document.addEventListener('click', display(alertName, person));
}
function display(myFunc, myObj) {
name = myObj.name;
myFunc();
}
start();
here is fiddle:
function start() {
var person = {
        name : "John"
    };
    function alertName() {
        alert(""+this.name.toUpperCase() + "");
    }
    document.addEventListener('click', start(alertName, person));
}
function display(myFunc, myObj) {
name = myObj.name;
myFunc();
}
start();
body {
background-color:yellow;
}
<body>
</body>
The issue here in that addEventListener second parameter need to be the function you want to invoke when the event is trigger.
In your exemple, you passed an instruction and not a function. What you can do is add the display() call inside a function body, and pass that function as the second parameter :
function start() {
var person = {
        name : "John"
    };
    function alertName() {
        alert(""+this.name.toUpperCase() + "");
    }
    document.addEventListener('click', function() {
display(alertName, person)
});
}
function display(myFunc, myObj) {
name = myObj.name;
myFunc();
}
start();
You need to understand that display is a function and by display(alertName, person) you are calling it immediately, not as a event callback. However addEventListener needs function reference as the second parameter so it means that when called display(alertName, person) must return a new function that will call alertName (which is a reference) from inside.
Finally, this.name inside alertName implies that it needs to be invoked in context of myObj, use Function.prototype.call to do it.
function start() {
var person = {        
name: "John"    
}
function alertName() {        
alert("" + this.name.toUpperCase() + "");    
}
document.addEventListener('click', display(alertName, person));
}
function display(myFunc, myObj) {
return function () {
myFunc.call(myObj)
}
}
start();
Click somewhere.

Use of debounce on Ext 3.4 framework

I want to implement the debounce function on Ext.Button, so I extended it and override the onClick function, like this:
MyButton = Ext.extend(Ext.Button, {
onClick: function(e) {
var that = this;
var args = e;
clearTimeout(this.timeoutDebounce);
this.timeoutDebounce = setTimeout(function(){
MyButton.superclass.onClick.apply(that, [args])
}, this.debounce);
}
});
Debounce is a parameter passed on the x-type declaration.
The problem here is that the "args" parameter I'm passing to onClick has changed when it's called from "click" to "mouvemove" and it doesn't fire the events it should.
Is there a way to record the "e" parameter received in the function to pass to onClick on superclass?
The function passed to setTimeout must be wrapped in order to keep the value presented in current scope:
function createCallback(args) {
return function() {
MyButton.superclass.onClick.apply(that, [args]);
}
}
Also, e is passed by reference, so you need to create a copy of it. Using ExtJS, you can use Ext.apply method:
Ext.apply({}, e);
The full code should be:
var MyButton = Ext.extend(Ext.Button, {
onClick: function(e) {
var that = this;
function createCallback(args) {
return function() {
MyButton.superclass.onClick.apply(that, [args]);
// you can also use call since you know the arguments:
// MyButton.superclass.onClick.call(that, args);
}
}
clearTimeout(this.timeoutDebounce);
var copy = Ext.apply({}, e);
this.timeoutDebounce = setTimeout(createCallback(copy), this.debounce);
}
});
You should clone the object:
var args = Ext.apply({}, e);
this.timeoutDebounce = setTimeout((function(args){
return function(){MyButton.superclass.onClick.apply(that, [args])};
})(args), this.debounce);

Why object property became undefined when using setInterval

As below code, I make an object named "test", and give it properties and method.
The property came from its argument.
And I try to call the method every 2 sec after onload, and the result shows undefined.
But if I only call the method not using setInterval(), like this
window.onload = function() {
giveword.showWord();
}
I'll be able to show the text "Hi".. Why is that?
var giveword = new test("Hi");
function test(word) {
this.word = word;
}
test.prototype.showWord = function() {
document.getElementById("msg_box").innerHTML = this.word;
}
window.onload = function() {
setInterval(giveword.showWord, 2000);
}
Thanks for help...
The reason is because in your test.prototype.showWord function your this object is referring to the context in which the function is called, which is the window object when called from setInterval.
I think what you want to do is use a closure to make the context of showWord() be the giveword instance like this:
var giveword = new test("Hi");
function test(word) {
this.word = word;
}
test.prototype.showWord = function() {
document.getElementById("msg_box").innerHTML = this.word;
}
window.onload = function(){
setInterval(function(){giveword.showWord();}, 2000); // <<-- here's the closure
}
The difference is that with the closure you're telling the setInterval function to call a function within the context as it was when the setInterval was declared. When setInterval was declared there was a variable in scope called giveword that had a method showWord() that returns the value of your initial input. (Closures are hard to explain, and I'm afraid you'd be best served by someone else explaining them if you need more info.)
This solution this now so easy, use an arrow function in setInterval. Here is an example using setInterval inside of an object method.
const mobile = {
make: 'iPhone',
model: 'X',
battery: 10,
charging: false,
charge: function() {
if(this.battery < 100) {
this.charging = true;
console.info('Battery is charging...');
let interval = setInterval(() => {
this.battery = this.battery + 10;
console.info(mobile.battery);
if( this.battery === 100){
this.charging = false;
clearInterval(interval);
console.info('Battery has finished charging.');
}
}, 100);
}
else {
console.info('Battery does not need charging.');
}
}
}

Javascript - Call a Local Function / Property While in Global Scope

Let's say I have the following JavaScript
function myGlobalFunction(){
function firstInnerFunction(){
return "rainbows";
}
function secondInnerFunction(){
function innerInnerFunction(){
return "clouds";
}
return innerInnerFunction();
}
return firstInnerFunction(); //valid call
}
Is there anyway I can call firstInnerFunction() in the global scope? If so(and better yet), can I go two levels down and call innerInnerFunction() from the global scope?
What are you trying to achieve in doing something like that? I would suggest something like the following:
var myGlobalFunction = {
var innerInnerFunction() { return "clouds"; }
get firstInnerFunction() { return "rainbows"; }
get secondInnerFunction() { return innerInnerFunction(); }
};
You can then call firstInnerFunction() with something like this:
myGlobalFunction.firstInnerFunction;
as for calling innerInnerFunction() from the global scope, myGlobalFunction.secondInnerFunction() will serve the same purpose as calling innerInnerFunction() directly.
In short, no. JavaScript is function scoped, so everything inside is hidden from the outside. So in order to access the inner functions you'll need to expose them somehow.
Absolute simplest (but ugly) option is to do something like this:
var secondInnerCopy;
function myGlobalFunction(){
function firstInnerFunction(){
return "rainbows";
}
function secondInnerFunction(){
function innerInnerFunction(){
return "clouds";
}
return innerInnerFunction();
}
secondInnerCopy = secondInnerFunction;
return firstInnerFunction(); //valid call
}
myGlobalFunction();
secondInnerCopy(); //valid (only after myGlobalFunction called though)
Better option would be to restructure into an object graph with functions:
var global = {
myGlobalFunction: function(){
return this.inner.firstInnerFunction(); //valid call
},
inner: {
firstInnerFunction: function() {
return "rainbows";
},
secondInnerFunction: function(){
return this.inner.innerInnerFunction();
},
inner: {
innerInnerFunction: function(){
return "clouds";
}
}
}
};
global.myGlobalFunction();
global.inner.inner.innerInnerFunction();
//etc...
I don't think that this is possible, however I could be wrong. You could do something like this to access the nested functions via the top level function.
function A(x) {
function B(y) {
function C(z) {
alert(x + y + z);
}
C(3);
}
B(2);
}
A(1); // alerts 6 (1 + 2 + 3)
Another Example
function addSquares(a,b) {
function square(x) {
return x * x;
}
return square(a) + square(b);
}
a = addSquares(2,3); // returns 13
b = addSquares(3,4); // returns 25
c = addSquares(4,5); // returns 41
Check this link, it has some good information on functions and nested functions in Javascript. Javascript Function Scope
I believe something like this would also work, though I like what Alconja did.
var myGlobalFunction = {
firstInnerFunction: function(){
return "rainbows";
},
secondInnerFunction : function(){
var innerInnerFunction = function(){
return "clouds";
}
var inninnerFuncTwo = function(){
return 'more stuff';
}
return {
inn : innerInnerFunction,
inn2: inninnerFuncTwo
}
}
}
myGlobalFunction.secondInnerFunction().inn();
myGlobalFunction.secondInnerFunction().inn2();
If you want a call to globalFunction to define firstInnerFunction, you can do that as follows
function globalFunction() {
firstInnerFunction = function() { return "rainbows" ; } ;
}
For innerInner function, you can do as follows
function globalFunction() {
firstInnerFunction = function() { return "rainbows" ; } ;
secondInnerFunction = function() {
innerInnerFunction = function() { return "clouds" ; } ; }
}
Now you can do this
globalFunction() ; // defines firstInnerFunction and secondInnerFunction in the global scope
firstInnerFunction() ; // returns "rainbows"
secondInnerFunction() ; // defines innerInnerFunction
innerInnerFunction() ; // returns "clouds"

Passing objects to events jQuery

In this example I'm trying to iterate over the properties of an object that's passed to a click handler, but I am getting unexpected results.
Here's the fiddle
So with a JS script like
$(document).ready(function ()
{
Label = function (name, toDate, fromDate)
{
this.name = name;
this.toDate = toDate;
this.fromDate = fromDate;
}
lbl = new Label('John', 'Today', 'Yesterday');
$('#btnSubmit').click(function ()
{
for (var i in lbl)
{
console.log(i);
}
});
$('#btnSubmit2').click(function (Label)
{
for (var i in Label)
{
console.log(i);
}
});
});
Why can't I pass an object in the function of a click event and iterate over its properties instead of using the forin loop like I did in the btnSubmit example?
The callback is always called with the event as argument. When you write click(function(Label){ you only give that event variable the name Label (thus shadowing your outside constructor).
But you can access the variables defined in the outer scope, so what you want is probably
var lbl = new Label('John', 'Today', 'Yesterday');
$('#btnSubmit').click(function(){
for (var i in lbl) {
console.log(i, lbl[i]); // for example "name", "John"
}
});

Categories

Resources