i use **{} **for folding variable statements in javascript.
Just wondering what does it cost in computation?
{
var test = document.getElementById("test");
var testClass = test.className;
}
scripts process fine but not assured if it is right thing to do
Related
I have the following two options to run a script with a string:
Option A:
var script = document.createElement('script');
script.innerHTML = "function foo(){console.log('Hello!')}";
script.type = "text/javascript";
document.body.appendChild(script);
foo();
Option B:
eval("function foo(){console.log('Hello!')}");
foo();
They both print Hello in the console.
If I want to let users dynamically run scripts in my app, which one is a better(safer, faster) option?
If I want to let users dynamically run scripts in my app ...
There's nothing safe with this requirement, and none of the options is CSP friendly.
The "best" approach you could use though is Function, 'cause at least that doesn't reaches/target the local scope, like eval would do, keeping the execution within its function body scope.
The question now would be how to make the code available to the user without interfering with the rest of the code, or the previous call, or the global scope.
For this specific case I suggest a CommonJS like approach, so that your users must define what they are exporting in their code.
Example
const CommonJS = code => {
const exports = {};
const module = {exports};
const runtime = Function(
'module', 'exports',
`"use strict";${code};return module`
);
return runtime(module, exports);
};
const {exports} = CommonJS(`
module.exports = function foo(){console.log('Hello!')}
`);
exports();
Using this approach your users can define a single, or multiple, exports, like in Node.js, becoming familiar with the CommonJS module system, and avoiding any sort of global scope pollution, thanks to the "use strict" directive and the Function closure itself.
Alternatively, you can const foo = Function('return(' + code + ')')() but that requires code to be a single expression, so I would personally stick with the previous approach.
I'm running against a wall here, maybe it's just a small problem where I can't see the solution due to my inexperience with NodeJS.
Right now I'm constructing a BT device which will be controlled by a master application and I have settled for the prototyping on a Raspberry PI 3 with NodeJS using the Bleno module.
So far everything worked fine, the device gets found and I can set and get values over Bluetooth. But to separate the different "programs" which the device could execute from the Bluetooth logic (because of loops etc.) I have opted to extract these into external NodeJS files.
The idea here was to use the NodeJS fork module and control the starting and stoppping of those processes through the main process.
But herein my problems start. I can fork the different JavaScript files without problem and these get executed, but I can't get them to stop and I don't know how to fix it.
Here's the code (simplified):
var util = require('util');
var events = require('events');
var cp = require('child_process');
...
var ProgramTypeOne = {
NONE: 0,
ProgramOne: 1,
...
};
...
var currentProgram=null;
...
function BLEDevice() {
events.EventEmitter.call(this);
...
this.currentProgram=null;
...
}
util.inherits(BLELamp, events.EventEmitter);
BLELamp.prototype.setProgram = function(programType, programNumber) {
var self = this;
var result=0;
if(programType=="ProgramTypeOne "){
if(programNumber==1){
killProgram();
this.currentProgram=cp.fork('./programs/programOne');
result=1;
}else if(programNumber==2){
...
}
self.emit('ready', result);
};
...
module.exports.currentProgram = currentProgram;
...
function killProgram(){
if(this.currentProgram!=null){
this.currentProgram.kill('SIGTERM');
}
}
There seems to be a problem with the variable currentProgram which, seemingly, never gets the childprocess from the fork call.
As I have never worked extensivley with JavaScript, except some small scripts on websites, I have no idea where exactly my error lies.
I think it has something to do with the handling of class variables.
The starting point for me was the Pizza example of Bleno.
Hope the information is enough and that someone can help me out.
Thanks in advance!
Since killProgram() is a standalone function outside of the scope of BLELamp, you need to call killProgram with the correct scope by binding BLELamp as this. Using apply (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply) should resolve it. The following I would expect would fix it (the only line change is the one invoking killProgram):
BLELamp.prototype.setProgram = function(programType, programNumber) {
var self = this;
var result=0;
if(programType=="ProgramTypeOne "){
if(programNumber==1){
killProgram.apply(this);
this.currentProgram=cp.fork('./programs/programOne');
result=1;
}else if(programNumber==2){
...
}
self.emit('ready', result);
};
As a side note, your code is kind of confusing because you have a standalone var currentProgram then a couple prototypes with their own bound this.currentPrograms. I would change the names to prevent confusion.
I have my code:
var User = function() {
...
}
and the test code using IIFE:
(function() { // test new user
var user = new User();
if (typeof user === 'undefined') {
console.log("Error: user undefined");
}
...
}());
both in the same js file. Works great! But, as the program grows, this is becoming too refractory for me to manage, as I have a piece of test code for every piece of business logic.
I've been taught to keep all my js in the same file, (minified is good) in production, but is there a best-practical way to keep my test code in a different file during development?
I was thinking I could use a shell script to append the test code to the production code when I want to run the tests, but I'd prefer a cross-platform solution.
I don't want or need a framework solution, I want to keep it light -- does node have anything built-in for this sort of thing?
Node has two expressions for this case. First:
module.exports = name_of_module;
Which is to export module for example function, object or something similar. And the second:
var module_name = require('Path/to/module');
to import it from other file. If you want to export IIFE you must assign it to global variable and module.export name of variable.
I am fully aware of the dangers of eval and such, so please don't waste your time commenting on how these hacks are hacks.
Say I'm using a third-party JavaScript library, but I'd like all of it's code to be defined within a particular namespace... that I also don't control. For example:
<script src="http://example.com/library.js>
<!-- library.js contains:
var x = 0;
function foo() {}
-->
I'd like to be able to define x and foo in the context of, say, namespace Bar, instead of the global context (window).
Assuming Bar is defined, but in another external js file that I don't control, I have tried some hacks, for example:
<script>
var externalCode = $.ajax("http://example.com/library.js");
eval.call(Bar, externalCode);
// and also tried:
(function(str){ eval(str); }).call(Bar, externalCode);
</script>
But I am not able to access Bar.x nor invoke Bar.foo().
Basically, I want to achieve the results I would get if I pasted the contents of library.js inside my Bar namespace, a la:
var Bar = {
x: 0,
foo: function() {}
}
However, I am trying to do this when I also lack control over the Bar namespace. Hence I can't "copy and paste." Another related example is how we can "punch in" new methods into pre-existing class definitions in Ruby.
Lastly, my specific use case is that I'm trying to "inject" everything from p5.js into the Opal namespace.
A simple solution that works in browsers today is:
<script src="http://example.com/library.js>
<!-- library.js contains:
var x = 0;
function foo() {}
-->
<script>
$.ajax('/library.js', function(jsString) {
var wrapped = `function() {
${jsString};
Bar.x = x;
Bar.foo = foo;
}();`
eval(wrapped);
});
</script>
However, a solution that doesn't require listing modules is EcmaScript 6 modules. If you transpile it with https://babeljs.io/, it can work with today's browsers.
//------ main.js ------
import * as Bar from 'lib';
console.log(Bar.foo()); // no error
console.log(Bar.x); // 0
If you need it to work in all browsers today, and don't want to transpile your code, you'd need the first example, which could be generalized as
function importIntoNs(ns, scriptUrl, symbolNames) {
$.ajax(scriptUrl, function(jsString) {
var wrapped = `(function() {
${jsString};`;
symbolNames.forEach(symbolName => {
wrapped += 'this.' + symbolName + ' = symbolName;\n' ;
});
wrapped += '})';
eval(wrapped).apply(ns);
}
}
importIntoNs(Bar, 'http://example.com/library.js', ['x', 'foo']);
If anyone wants to downvote because of the eval, remember that the OP is already going to execute the script no matter what if they put it in a <script> tag.
Here's a working example without fetching the script.
function importScriptIntoNs(ns, jsString, symbolNames) {
var addSymbols = '';
symbolNames.forEach(symbolName => {
addSymbols += 'this.' + symbolName + ' = ' + symbolName + ';\n';
});
var wrapped = `(function() {;
${jsString}
${addSymbols}
})`;
eval(wrapped).apply(ns);
}
var Bar = {};
var jsString = `
var x = 'It works';
function foo() {alert(x)}
`;
importScriptIntoNs(Bar, jsString, ['x', 'foo']);
Bar.foo()
One way to handle libraries and other dependencies without polluting the global scope is to use some kind of Asynchronous Module Definition. A good one that I like to use and recommend is Require.js.
The whole idea behind it is that you're able to bundle your libraries and dependencies into modules and call on them when you need, without simply loading everything on the global scope.
Here is an example of how you might use it in your situation:
require(['http://example.com/library.js'], function(Bar){
// library.js is now bound within this scope under the alias Bar
});
I usually break down the parts of my app into their own modules and files that exist under one global object. For the production code I combine all the files on one master.js file. Because I'm writing the code in different files and don't want to worry about the order they're loaded I check if the global object 'App' exists, and if it doesn't create an empty object to store the module in.
So if I have 10 modules then in the combined file it will run var App = App || {}; 10 times when it only needs to run once (at the start). My question is, is that a big deal in terms of performance, is it worth going in at the end and removing the unnecessary code? For smaller apps I don't think it's a big deal, but just wondering if this is a bad strategy to use for bigger apps.
// module_1.js
var App = App || {};
App.Module_1 = (function(){
// code
}());
// module_2.js (different file)
var App = App || {};
App.Module_2 = (function(){
// code
}());
Even if var App = App || {} runs 100 times, you will not notice any difference (only on very slow systems), so I'd say: just leave it.
Generally, don't optimize prematurely, look where the real bottlenecks are and optimize those.
BTW, those extra anonymous, self-invoking functions are not necessary: when using
App.Module_X = function(){
// code
};
you variables declared using var already are within the scope of App.Module_X.