Using 'this' in nested function in class [duplicate] - javascript

This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
Nested function parameters and 'this' context in Javascript
I'm currently having problems to design my JS classes as desired due to a problem using 'this' in a nested class function call. Don't know how to describe it better so here's a sample what I mean.
test.html
<!DOCTYPE html>
<html class="main" lang="en">
<head>
<meta charset="utf-8">
<script type="text/javascript" src="test.js"></script>
<script type="text/javascript">
function doIt() {
var myTestClass = new TestClass();
}
</script>
</head>
<body>
<button onclick="doIt();">Do it!</button>
</body>
</html>
test.js
function TestClass() {
// this is working
this.alertValue('This works');
// this is not working
setTimeout(function(){this.alertValue('This does not work!')}, 1000);
}
TestClass.prototype.alertValue = function(value) {
alert('Value is: ' + value);
}
Of course this is just a simplified example to demonstrate the problem I mean.
So how could I use the 'this' identifier within the function inside the setTimeout call or how would be a better / the correct way to achieve that?
Thanks a lot for your help in advance!
Cheers

Save the value of this in a variable (self) and then you can access it within setTimeout.
function TestClass() {
this.alertValue('This works');
var self = this;
setTimeout(function() {
self.alertValue('This does not work!')
}, 1000);
}

Related

Troubleshooting inability to execute onclick handler [duplicate]

This question already has answers here:
What is the scope of variables in JavaScript?
(27 answers)
Closed 2 years ago.
Following this page, I'm finding that I can't execute an 'onclick' handler like the handler set up here:
function handler() {
console.log(5);
}
<button onclick="handler()"></button>
This is the only module I use: <script type="module" src="../js/js_test.js"></script>. It's in the header.
This is the error I get:
It works when I have this in my module:
let button = document.querySelector('button');
button.onclick = handler;
Any ideas?
P.s. I can't access variables I write on my module on the console. I thought I once could do this. Don't know if that's helpful.
you can also use export and import. exporting your functions and importing it to another file
In js_test.js do
export function handler() {
console.log(5);
}
In the html do
<html>
</head>
<script type="module" src="../js/js_test.js"></script>
<script type="module">
import {handler} from '../js/js_test.js';
document.onload = function(){
document.getElementById('myButton').addListener("click", handler);
};
</script>
</head>
<body>
<button id="myButton"></button>
</body>
</html>
EDIT per the suggestion of Aks Jacoves
An old way of doing module was
In js_test_old.js do
(function _module_x (global) {
global.myNamespace = global.myNamespace || {};
global.myNamespace.handler = _handler_;
function _handler_ () {
console.log(5);
}
})(window); // or })( (function(){return this;})() ); // this works for both Node.js and html
In the html do
<html>
</head>
<script src="../js/js_test_old.js"></script>
</head>
<body>
<button onclick="myNamespace.handler()"></button>
</body>
</html>
Be sure to add a listener if the html element has finished loading
document.onload = function(){
function handler(){
console.log(5);
}
}

Fail to create a plugin in Javascript [duplicate]

This question already has answers here:
How does the "this" keyword work, and when should it be used?
(22 answers)
Closed 5 years ago.
I am new to Javascript programming and I'm trying to learn it by myself. I tried to make a plugin which allows element assigned moving back and forth, but it does not work. Could anyone help me and tell me what the problem with my code? Below is the code with I am trying to develop my plugin.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
Hello, world
<img src="car.png" style="width:100px; height:60px">
<p>Hello, world</p>
<script src="https://code.jquery.com/jquery-3.1.0.js"></script>
<script>
(function( $ )
{
$.fn.showLinkLocation = function()
{
move();
function move()
{
$(this).animate({left: '500px'}, 1000).animate({left: '0px'}, 1000);
move();
};
};
}( jQuery ));
$( "a" ).showLinkLocation();
</script>
</body>
</html>
(function($) {
$.fn.showLinkLocation = function() {
this.animate({
left: '500px'
}, 1000).animate({
left: '0px'
}, 1000);
return this;
};
})(jQuery);
$("a").showLinkLocation();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Hello, world
Cause :
You got, recursive call not gonna break, infinite loop :
function move(){
...
move();
};
Explanation:
Using jQuery rather than $ ensures there are no conflicts with other JavaScript libraries. All our internal code should also refer to jQuery rather than $.
(function($) {
$.fn.showLinkLocation = function() { ... };
})(jQuery);
This function runs immediately and is passed jQuery as a parameter named $. Since $ is a local variable, we can assume that it always refers to the jQuery library rather than another library that grabbed the global $ variable first.
this refers to jQuery, so we can access jQuery's methods directly, like this.each(...
return this; return the jQuery object so other methods can be chained
I think what was wrong with your code is that, inside the inner move function, you did not have access to its outer this variable, which was the target element in this case.
So, you needed to keep outer this in a separate variable, so it's not overriden by the function in that function's context. In any case, I think Akshay Hegde's solution below is much cleaner.
Another issue is that you are calling move() repeatedly which eventually will crash the browser. You should wait for the first animation to complete, before starting it again.
(function( $ ) {
$.fn.showLinkLocation = function() {
var $this = this;
move();
function move(){
console.log("move called" + new Date().getTime() );
$this.addClass("animating").animate({left: '500px'}, 1000).animate({left: '0px'}, 1000);
//move();
};
};
}( jQuery ));
$( "a" ).showLinkLocation();
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
Hello, world
<img src="car.png" style="width:100px; height:60px">
<p>Hello, world</p>
<script src="https://code.jquery.com/jquery-3.1.0.js"></script>
</body>
</html>

how to create a js function and use it on another files [duplicate]

I wanted to call a function defined in a first.js file in second.js file. Both files are defined in an HTML file like:
<script type="text/javascript" src="first.js"></script>
<script type="text/javascript" src="second.js"></script>
I want to call fn1() defined in first.js in second.js. From my searches answers were if first.js is defined first it is possible, but from my tests I haven't found any way to do that.
Here is my code:
second.js
document.getElementById("btn").onclick = function() {
fn1();
}
first.js
function fn1() {
alert("external fn clicked");
}
A function cannot be called unless it was defined in the same file or one loaded before the attempt to call it.
A function cannot be called unless it is in the same or greater scope then the one trying to call it.
You declare function fn1 in first.js, and then in second you can just have fn1();
1.js:
function fn1 () {
alert();
}
2.js:
fn1();
index.html :
<script type="text/javascript" src="1.js"></script>
<script type="text/javascript" src="2.js"></script>
You could consider using the es6 import export syntax. In file 1;
export function f1() {...}
And then in file 2;
import { f1 } from "./file1.js";
f1();
Please note that this only works if you're using <script src="./file2.js" type="module">
You will not need two script tags if you do it this way. You simply need the main script, and you can import all your other stuff there.
1st JS:
function fn(){
alert("Hello! Uncle Namaste...Chalo Kaaam ki Baat p Aate h...");
}
2nd JS:
$.getscript("url or name of 1st Js File",function(){
fn();
});
You can make the function a global variable in first.js
and have a look at closure and do not put it in document.ready put it outside
you can use ajax too
$.ajax({
url: "url to script",
dataType: "script",
success: success
});
same way you can use jquery getScript
$.getScript( "ajax/test.js" )
.done(function( script, textStatus ) {
console.log( textStatus );
})
.fail(function( jqxhr, settings, exception ) {
$( "div.log" ).text( "Triggered ajaxError handler." );
});
declare function in global scope with window
first.js
window.fn1 = function fn1() {
alert("external fn clicked");
}
second.js
document.getElementById("btn").onclick = function() {
fn1();
}
include like this
<script type="text/javascript" src="first.js"></script>
<script type="text/javascript" src="second.js"></script>
use "var" while creating a function, then you can access that from another file. make sure both files are well connected to your project and can access each other.
file_1.js
var firstLetterUppercase = function(str) {
str = str.toLowerCase().replace(/\b[a-z]/g, function(letter) {
return letter.toUpperCase();
});
return str;
}
accessing this function/variable from file_2.js file
firstLetterUppercase("gobinda");
output => Gobinda
It should work like this:
1.js
function fn1() {
document.getElementById("result").innerHTML += "fn1 gets called";
}
2.js
function clickedTheButton() {
fn1();
}
index.html
<html>
<head>
</head>
<body>
<button onclick="clickedTheButton()">Click me</button>
<script type="text/javascript" src="1.js"></script>
<script type="text/javascript" src="2.js"></script>
</body>
</html>
output
Try this CodePen snippet: link .
Please note this only works if the
<script>
tags are in the body and NOT in the head.
So
<head>
...
<script type="text/javascript" src="first.js"></script>
<script type="text/javascript" src="second.js"></script>
</head>
=> unknown function fn1()
Fails and
<body>
...
<script type="text/javascript" src="first.js"></script>
<script type="text/javascript" src="second.js"></script>
</body>
works.
This is actually coming very late, but I thought I should share,
in index.html
<script type="text/javascript" src="1.js"></script>
<script type="text/javascript" src="2.js"></script>
in 1.js
fn1 = function() {
alert("external fn clicked");
}
in 2.js
fn1()
Use cache if your server allows it to improve speed.
var extern =(url)=> { // load extern javascript
let scr = $.extend({}, {
dataType: 'script',
cache: true,
url: url
});
return $.ajax(scr);
}
function ext(file, func) {
extern(file).done(func); // calls a function from an extern javascript file
}
And then use it like this:
ext('somefile.js',()=>
myFunc(args)
);
Optionally, make a prototype of it to have it more flexible. So that you don't have to define the file every time, if you call a function or if you want to fetch code from multiple files.
first.js
function first() { alert("first"); }
Second.js
var imported = document.createElement("script");
imported.src = "other js/first.js"; //saved in "other js" folder
document.getElementsByTagName("head")[0].appendChild(imported);
function second() { alert("Second");}
index.html
<HTML>
<HEAD>
<SCRIPT SRC="second.js"></SCRIPT>
</HEAD>
<BODY>
method in second js<br/>
method in firstjs ("included" by the first)
</BODY>
</HTML>
window.onload = function(){
document.getElementById("btn").onclick = function(){
fn1();
}
// this should work, It calls when all js files loaded, No matter what position you have written
});
// module.js
export function hello() {
return "Hello";
}
// main.js
import {hello} from 'module'; // or './module'
let val = hello(); // val is "Hello";
reference from https://hype.codes/how-include-js-file-another-js-file
My idea is let two JavaScript call function through DOM.
The way to do it is simple ...
We just need to define hidden js_ipc html tag.
After the callee register click from the hidden js_ipc tag, then
The caller can dispatch the click event to trigger callee.
And the argument is save in the event that you want to pass.
When we need to use above way ?
Sometime, the two javascript code is very complicated to integrate and so many async code there. And different code use different framework but you still need to have a simple way to integrate them together.
So, in that case, it is not easy to do it.
In my project's implementation, I meet this case and it is very complicated to integrate. And finally I found out that we can let two javascript call each other through DOM.
I demonstrate this way in this git code. you can get it through this way. (Or read it from https://github.com/milochen0418/javascript-ipc-demo)
git clone https://github.com/milochen0418/javascript-ipc-demo
cd javascript-ipc-demo
git checkout 5f75d44530b4145ca2b06105c6aac28b764f066e
Anywhere, Here, I try to explain by the following simple case. I hope that this way can help you to integrate two different javascript code easier than before there is no any JavaScript library to support communication between two javascript file that made by different team.
<html>
<head>
<link rel="stylesheet" type="text/css" href="css/style.css" />
</head>
<body>
<div id="js_ipc" style="display:none;"></div>
<div id="test_btn" class="btn">
<a><p>click to test</p></a>
</div>
</body>
<script src="js/callee.js"></script>
<script src="js/caller.js"></script>
</html>
And the code
css/style.css
.btn {
background-color:grey;
cursor:pointer;
display:inline-block;
}
js/caller.js
function caller_add_of_ipc(num1, num2) {
var e = new Event("click");
e.arguments = arguments;
document.getElementById("js_ipc").dispatchEvent(e);
}
document.getElementById("test_btn").addEventListener('click', function(e) {
console.log("click to invoke caller of IPC");
caller_add_of_ipc(33, 22);
});
js/callee.js
document.getElementById("js_ipc").addEventListener('click', (e)=>{
callee_add_of_ipc(e.arguments);
});
function callee_add_of_ipc(arguments) {
let num1 = arguments[0];
let num2 = arguments[1];
console.log("This is callee of IPC -- inner-communication process");
console.log( "num1 + num2 = " + (num1 + num2));
}
better late than never
(function (window) {const helper = { fetchApi: function () { return "oke"}
if (typeof define === 'function' && define.amd) {
define(function () { return helper; });
}
else if (typeof module === 'object' && module.exports) {
module.exports = helper;
}
else {
window.helper = helper;
}
}(window))
index html
<script src="helper.js"></script>
<script src="test.js"></script>
in test.js file
helper.fetchApi()
I have had same problem. I have had defined functions inside jquery document ready function.
$(document).ready(function() {
function xyz()
{
//some code
}
});
And this function xyz() I have called in another file. This doesn't working :) You have to defined function above document ready.
TLDR: Load Global Function Files first, Then Load Event Handlers
Whenever you are accessing an element within a JS file or <script> block, it is essential to check to make sure that element exists, i.e., jQuery's $(document).ready() or plain JS's document.addEventListener('DOMContentLoaded', function(event)....
However, the accepted solution does NOT work in the event that you add an event listener for the DOMContentLoaded, which you can easily observe from the comments.
Procedure for Loading Global Function Files First
The solution is as follows:
Separate the logic of your JS script files so that each file only contains event listeners or global, independent functions.
Load the JS script files with the global, independent functions first.
Load the JS script files with event listeners second. Unlike the other previous files, make sure to wrap your code in document.addEventListener('DOMContentLoaded', function(event) {...}). or document.Ready().

Why do I get this JavaScript ReferenceError

What am doing wrong. I try to make object but when i try to initialize i get this error in console: I try to put all in document.ready and whitout that but dont work. In both case i have some error. Am new sorry for dumb question
ReferenceError: Circle is not defined
var obj = new Circle;
JS
$(function(){
var Circle = {
init: function() {
console.log("Circle initialized");
}
};
});
HTML
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script src="javascript/circle.js"></script>
<script>
$(document).ready(function(){
var obj = new Circle;
obj.init();
})
</script>
</head>
<body>
<div id="test" >TODO write content</div>
</body>
</html>
NEW UPDATE
$(function(){
window.Circle = {
init: function() {
console.log("Circle initialized");
}
};
window.Circle.init();
});
....
<head>
<script>
window.Circle().init();
</script>
</head>
You've defined your "Circle" function inside another function — the anonymous function you pass in as a a "ready" handler. Therefore, that symbol ("Circle") is private to that function, and not visible to the other code.
You can make it global like this:
window.Circle = {
// ...
};
You could also add it to the jQuery namespace (may or may not be appropriate; depends on what you're doing), or you could develop your own namespace for your application code. Or, finally, you could consider combining your jQuery "ready" code so that the "Circle" object and the code that uses it all appears in the same handler.
edit — another possibility is to move your "Circle" declaration completely out of the "ready" handler. If all you do is initialize that object, and your property values don't require any work that requires the DOM or other not-yet-available resources, you can just get rid of the $(function() { ... }) wrapper.
1) you are assigning Circle in a function context, not as a global. You can only use it there unless you expose it to global.
2) you are calling Circle as a constructor, but Circle is not a function.
This solves both issues:
var Circle = function () {};
Circle.prototype.init = function () {
console.log('Circle initialized.');
};
var obj = new Circle();
obj.init();

jquery - call function in external js file

If I have this code in a file called custom.js:
var kennel = function(){this._init();};
kennel.prototype = {
_init: function() {
this.setListeners();
},
setListeners: function(){
...
},
getCats: function(){
alert("Get cats");
}
};
How do I call getCats() from some arbitrary html file?
First of all you would include the javascript by using the <script> tag, generally in the <head>, then after that you can create another <script> tag which you can place your own javascript code in that is specific to the page, and which uses the functionality made available by the included file. For example:
<head>
<script type="text/javascript" src="path/to/custom.js"></script>
<script type="text/javascript">
var myKennel = new kennel();
myKennel.getCats(); // alerts "Get cats"
</script>
</head>
Also, the code you have posted has nothing to do with jQuery - it is plain old, vanilla javascript.
This should be enough:
<script>
var k = new kennel();
k.getCats();
</script>
Here's a sample of it working: http://jsfiddle.net/NHaBb/
​

Categories