This question already has answers here:
What is the scope of variables in JavaScript?
(27 answers)
Closed 5 years ago.
I have a problem I've been searching SO for answers to, but nothing seem to do it for me. I've referenced a question that mimics my problem but the solution still don't solve my problem.
Accessing function in another .js file with $.getScript
My problem is as I've mentioned similar. I can't access a method inside a script file from another script file. These are my codes:
page.js
$(document).ready(function () {
$.getScript('script.js').done(function () {
$('#build').append(literals.test()); // $('#build') is a span tag in the HTML-file.
}).fail(function () {
console.warn('Unable to load script file.');
});
});
script.js
(function ($) {
var literals = {
test: function () {
return 'Hello world!';
}
};
})(jQuery);
This still returns the following error even though I've built it almost exactly the same way as in the answer of the referenced question.
Uncaught ReferenceError: literals is not defined at Object.<anonymous>
What am I doing wrong here?
Because when you create a closure, anything inside of it is only visible to other things in that scope.
In JS, all functions are closures.
(function(){
// this is a closure
})()
If you want to be able to get the literals functions from outside of the closure, one option is to return it from the function...
const literals = (function($){
return {
test: function () {
return 'Hello world!';
}
};
})(jQuery);
console.log(literals.test());
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Related
This question already has answers here:
Accessing an object's property from an event listener call in JavaScript
(6 answers)
Closed 2 years ago.
I have the following JS object in my code:
var myLibrary = {
name: "John",
// Functions
func1: function() {
alert(this.name);
},
func2: function() {
this.func1();
},
// On DOM loaded
onDOMLoaded: function() {
this.func1();
this.func2();
}
}
document.addEventListener('DOMContentLoaded', myLibrary.onDOMLoaded);
When I reference this code using a script tag, I get the following error (in reference to the call in func2):
Uncaught TypeError: this.func1 is not a function
This is especially weird because if I call the functions from within the DOM, they work perfectly. For example:
<button onclick="myLibrary.func1()">Func 1</button>
<button onclick="myLibrary.func2()">Func 2</button>
Clicking on the buttons does exactly what I want them to. What am I doing wrong here? And how can I fix this issue? Thanks for any help!
A demo can be found here: https://jsfiddle.net/gLxvsze0/
You should read about this is JS.
When you call myLibrary.func1() the function will be called with myLibrary context. But when you call just func1 (ie func1 = myLibrary.func1; func1()) this will be called with global Window context.
To solve your problem, you can use bind method, that creates new function linked with provided context:
document.addEventListener('DOMContentLoaded', myLibrary.onDOMLoaded.bind(myLibrary));
I think the simplest solution to the context issue is...
document.addEventListener('DOMContentLoaded',() => { myLibrary.onDOMLoaded(); });
I have been learning about encapsulation in Javascript with the module pattern. I want to give access to specific js files. From what I understand, it is only possible to restrict access to everything and give access to everything, is this correct?
smiley.js
(function(exports){
function smiley(string){
return string + ' :)';
};
exports.smiley = smiley;
})(this);
play.js
smiley('Hello');
Given an HTML file that includes smiley.js and play.js.
<script src='smiley.js'></script>
<script src='play.js'></script>
Is it possible to have another js file that does not have access to smiley.js but is also included in the HTML file?
Is there only global (window) scope and private scope or can I specify a scope for different files?
If I understand your question correctly, I would say:
const Script1 = (function () {
// Encapsulate the logic.
const Logic = {
sayHi () {
alert('Script1 says hi!');
},
shutUp () {
alert('Shut up!');
}
};
// Public attributes.
return {
sayHi () {
Logic.sayHi();
}
}
})();
document.addEventListener('DOMContentLoaded', function () {
Script1.sayHi(); // Will successfully work.
// Script1.shutUp(); -> Will say "Script1.shutUp is not a function".
});
Basically the idea is simple. Inside the self-invoking function you declare an object, which will hold the functions and data fields. Then from the return statement of the self-invoking function you can make functions publicly available. This way you can keep the ones you want private - private, and the ones you want available - you can make available. The same applies for multiple JS scripts. Just each script declares it's own self-invoking function. Script1, Script2, etc...
This question already has an answer here:
Cannot pass module functions to Page
(1 answer)
Closed 6 years ago.
i'm getting a ReferenceError when i call a function i defined myself inside the page.evaluate() of Phantom; what is the proper way to do that ?
for example:
function mySweetFunction(item) {
// process item....
}
page.evaluate(function(){
var item= document.getElementsById('item');
mySweetFunction(item);
});
then i'll get the error:
ReferenceError: Can't find variable: mySweetFunction
What is the proper way to do this ?
mySweetFunction is quite big, and i would prefer to keep it out of page.evaluate(...) if possible.
If you want to use a function inside page.evaluate() you have to put it there first:
page.evaluate(function(){
function mySweetFunction(item) {
// process item....
}
var item = document.getElementsById('item');
mySweetFunction(item);
});
This question already has answers here:
How can we know if a function is called from console or from source code
(3 answers)
Closed 7 years ago.
I want a particular JavaScript function to behave differently depending on if it's called within JavaScript code referenced from an HTML page or called from within a console. Is this possible? Something like the following:
function mySpecialFunc() {
if (inConsole())
console.log("You called me from the console!");
else
console.log("You called me from an HTML page or a JavaScript file linked from an HTML page, I think.");
}
Does something equivalent to the inConsole() function above exist?
Does this exist for at least just Chrome specifically, or Firefox specifically?
One way is to throw an error and check the stack trace for a string that is unique to the console's injection. Something like "InjectedScript"
Here is an example that works.
var f = function(){
var injected;
try {
throw new Error();
} catch (e) {
injected = e.stack.match('InjectedScript');
}
if (injected) {
console.log("Called from console");
} else {
console.log("Called from code");
}
}
// Add it to window so we can call it from the console.
window.f = f;
f();
Unfortunately there is no way to tell via system input, but you can do it "Manually" in a sense using overflow/overload functions. See here for a excellent tutorial on how to use overflow/overload in js.
So in your code that calls the function in javascript add an additional argument to the call that will tell the function it is not called from the console.
mySpecialFunc() <---- From console
mySpecialFunc(value) <---- From code
This question already has answers here:
Why can I not define functions in jQuery's document.ready()?
(6 answers)
Closed 8 years ago.
Im trying to understand how the browser works if it has 2 document.ready functions within it.
Sample code: Here printtest() module has a alert statement within my first document.ready function and its been called below but I don't see any action..
$(document).ready(function(){
function printtest(){
alert('Hi')
}
})
$(document).ready(function(){
printtest()
})
http://jsfiddle.net/7FuLc/1/
Since it has 2 document.ready function, how does the browser registers this function?
That code will not work because because javascript function creates a new scope variable every time it is declared. See the following:
$(document).ready(function(){
function printtest(){
alert('Hi')
}
})
$(document).ready(function(){
printtest() // ReferenceError, printtest undefined
})
compare this to
function printtest(){
alert('Hi')
}
$(document).ready(function(){
printtest() // alerts 'Hi'
})
$(document).ready(function(){
printtest() // alerts 'Hi'
})
This way, both $(document).ready(function(){}) understand what printtest is.
To solve your problem, here is the modified code,
var printtest;
$(document).ready(function(){
printtest = function (){
alert('Hi')
}
})
$(document).ready(function(){
printtest(); // alerts 'Hi'
})
Now this will work the way you intend it to be because you declare the variable outside the function. This is due to closure (closure is inner javascript function, meaning that any outside variable can be accessed inside the inner javascript function).
In conclusion, if you want a function that is accessible across different functions, declare it outside so that any other closure will be able to access it.