I would like to set variables on the fly using the console.
My code is wrapped like this:
( function () {
var debug = true;
// code here
} () )
I want to change debug on the fly using the console.
Should I move debug out of the self executing wrapper and pass it in using the global import?
Should I give the anonymous function a name, and set it using the "name spaced" name?
I have not used the console too much, but I assume it is made for things like this.
How is this usually done? What is best practice?
You could use a namespace with minimal effort as follows:
(function (foo) {
foo.debug = true;
}(FOO = FOO || {}));
FOO.debug = false;
I would go with this type of solution over using an explicit global because it isn't really more cumbersome and with variable names like debug there's a chance you might have a conflict.. even if you're working with code that is 100% yours.
Related
Given some basic class, such as a logical predicate class here:
const isACat = new Predicate(obj => obj.cat === true);
Is there a way to determine/trap/identify (perhaps via Reflection?) the context under which isACat is being "invoked/evaluated"? By "invoke/evaluate"--because I can't really think of a better word to use right now--I mean something like this:
console.log(isACat(object1)); // being "invoked/evaluated" as a function
console.log(isACat); // being "invoked/evaluated" as a non-function
I specifically mean this in the "runtime" sense, not in the typeof/instanceof sense.
For the ultimate goal of performing contingent behavior, such as (perhaps via a Proxy) returning a default function if that instance is being "invoked/evaluated" as a function.
Edit: Maybe in more precise terms, is there such a thing as a "default getter" when no further child prop is passed (i.e. isACat, but not isACat[ prop ])?
I am not seriously suggesting that you do any of the things presented bellow and you will spot their limitation immediately but I thought it was kind of fun to demonstrate.
[{dog: true}, {cat: true}].filter(isACat);// (referenced(), [{cat: true}])
isACat({dog: true}); // (referenced(), false)
let lives = 0;
lives += isACat; // (referenced(), 7)
`Felix ${isACat}` // (referenced(), "Felix is a cat")
The above requires the following, which you could probably generate with a Babel plugin or something (I mean: don't, obviously)
const referenced = (obj) => () => {
console.log(obj, 'was referenced');
return obj;
}
const _isACat = obj => obj.cat === true;
Object.defineProperty(_isACat, 'toString', {
value: () => 'is a cat'
});
Object.defineProperty(_isACat, 'valueOf', {
value: () => 7
});
Object.defineProperty(window, 'isACat', {
get: referenced(_isACat)
});
I don't know what I like the most about it: deceiving expectations thanks to getters, magical type coercion, or local variables leaking to the global scope. It is pure poetry.
More seriously, I don't think Javascript is the language for this but if for some reason you need meta-programming power, maybe give Clojure a go. You can also use macros with ClojureScript, which compiles to Javascript and has Javascript interop, but there is a runtime/compile time distinction which will limit what you can do.
No, there is no such thing. You're just accessing a variable, or whatever the reference to your object is stored in, and you get back a reference value. The object itself has no say about this process - it isn't even looked at yet. This is not "invocation" or "evaluation".
Really, if you need something like this, make the invocation explicit, and write isACat() (vs isACat(object) vs isACat.prop()).
When setting a breakpoint on the console.log statement, why would this be undefined in the debugger but the statement print with no issues? Am I missing something in regards to scope here?
export class OptionsSidebarComponent {
...
public filters: Object = new Object();
...
public generateFilters() {
for (let property in this.terms) {
if (this.terms.hasOwnProperty(property) && this.terms[property] !== null) {
if (!this.filters.hasOwnProperty(this.productGroup.id)){
this.filters[this.productGroup.id] = new Filters();
}
this.terms[property].forEach((term) => {
console.log(this.filters);
});
}
}
}
}
With typescript While debugging, keep in mind that transpilers can rename variables. Using the original name in the console without sourcemaps that include renaming will show you undefined even if the original value isn't. Make sure you use the transpiled name in watches or console commands.
When you're referencing this with your console.log statement inside its own class, you're using it in its relevant scope. Depending on the framework you are using, different terms are used to reference your class... AngularJS used $scope- Angular 2+ uses this to reference the current class (or current scope/context).
When you use this in your debugger you're using it outside of its scope. It no longer references the class you intend it to.
Each one of your components in Angular uses this to reference itself. Here's an article to explain in further detail: https://angular-2-training-book.rangle.io/handout/features/refresher_on_this.html
If we simplify it to basic javascript and look at your class as just a function a good example would be this:
function example(){
var anything = 10;
console.log(anything); //output: 10
}
console.log(anything); //undefined! we're out of scope :)
So looking at it from this perspective, this is nothing magical. It's just provided to us by Angular to make our references to other things inside our components easier.
I have code in a module which looks something like this:
var MyModule = module.exports;
MyModule.some_function = function(arg) {
// Do some code here
// Do some logging using the function name
// var function_name = calleeArgs.callee.toString().match(/function ([^\(]+)/)[1];
// BAD, this method doesnt have a name
};
The code above does not work as the function does not have a name.
As an alternative, I could do the following, in which case the log would contain the method name:
function _some_function(arg) {
// Do some code here
// Do some logging using the function name - BAD, this method doesnt have a name
// var function_name = calleeArgs.callee.toString().match(/function ([^\(]+)/)[1];
// GOO, this method doesnt have a name
}
MyModule.some_function = function(arg) {
_some_function(arg);
};
So my question is:
1.) Does this way of writing make any sense - as far as I understand _some_function() is local to this module so there will be no negative implications as far as global scope/access is concerned
2.) Does this (the second option) have any performance implications? (my guess would of course be no, or at least relatively negligible)?
1) I find that code style very confusing and bloated. I think the following is the cleanest approach:
function some_function(arg) {
// Do some code here
// Do some logging using the function name
}
// Put exports at the end
exports.some_function = some_function;
2) A function wrapping another function will add a negligible overhead, but it should be avoided if it adds no value.
I have module pattern done like this:
var A = (function(x) {
var methodA = function() { ... }
var methodB = function() { ... }
var methodC = function() { ... }
...
...
return {
methA: methodA,
methB: methodB
}
})(window)
This code let's me call only methA and methB() on A which is what I want and what I like. Now the problem I have - I want to unit test it with no pain ot at least with minimal efforts.
First I though I can simply return this but I was wrong. It returns window object.(can someone explain why?).
Second - I found solution somewhere online - to include this method inside my return block:
__exec: function() {
var re = /(\(\))$/,
args = [].slice.call(arguments),
name = args.shift(),
is_method = re.test(name),
name = name.replace(re, ''),
target = eval(name);
return is_method ? target.apply(this, args) : target;
}
This method let's me call the methods like this: A.__exec('methA', arguments);
It is almost what I want, but quite ugly. I would prefer A.test.methA() where test would never be used in production code - just for revealing private methods.
EDIT
I see people telling me to test the big thing instead of the small parts. Let me explain. In my opinion API should reveal only the needed methods not a bunch of internal functions. The internals because of their small size and limited functionality are much easier to test then test the whole thing and guess which part gone wrong.
While I may be wrong, I would still like to see how I could return references to all the methods from the object itself :).
Answer to your first question(you return this, but it returns window, not the object you wanted): in javascript this inside the function returns global object unless this function is a method of the object.
Consider next examples:
1) this points to the global object ():
function(){
return this;
}
2) this points to the object:
var obj = {
value: "foo",
getThisObject: function(){
return this;
}
}
Your case is example #1, because you have a function, that returns an object. This function is not a method of any object.
The best answer to your second question is to test only public methods, but if
that is so important for you, I can propose next:
create your modules dynamically on server side.
How it works:
create separate scripts for functionality you want;
create tests for these separate scripts;
create method that will combine scripts into one however you want;
to load script, reference to the combining scripts method.
Hopefully, it can solve your problem. Good luck!
Why not use namespaces to add your modules and public methods to js engine. Like this:
window['MyApp']['MODULE1'] = { "METHOD1" : {}, "METHOD2" : {}};
I write modules like this Sample module in JavaScript.
And test it like this: Simple unit testing in JavaScript
The use of eval() is generally not good idea.
So, I just noticed today that you can apparently run javascript in the chrome console. I had no idea you could do this. It's actually really cool.
In my rails app, I have an external javascript page. Some of the variables on that page I would like to be global so that all the functions in the JS file can access them. for example I have a map, and I would like the map object to be global in the javascript file because that way all my functions access the one map variable instead of creating their own, and I can break complex operations down into smaller functions.
This is all well and good I know how to do that and it's working perfectly. My problem now, can I protect the variables from outside? For example you can change the values of all the javascript class variables from the chrome console.. as well methods from for example the map are accessible and excecutable.. I have locked the map settings on one of the pages so it is not zoomable or movable, however from the console I can simply say map.setZoom(11) and the map will zoom to 11.. I can type map.dragable = true and bam u can drag the map.. I don't like this really..
It's not too terribly bad yet like the user enabling map drag and zoom isnt the worst thing in the world.. but still I'd like to disable this. Any ideas?
EDIT
Thanks all for the answers and comments. I guess I will just resort to not putting anything that can be turned malicious into my javascript, and do thing like pass my map variable to functions where necessary to slow people down.
You can use an immediately-invoked function (IIFE) expression to prevent your variables and functions from being exposed in the global scope:
var a = 10;
(function() {
var b = 20;
})();
window.a lets you view and modify a, but you cannot do that with b:
Try it out here
I'm more than sure that there's a way to edit b with Inspector, but I haven't taken the time to figure it out. Don't waste your time trying to prevent your users from modifying code that they can view.
You can't. Even if you wrap them into anonymous functions, user can get to them through debugger. As last resort he can simply intercept your traffic to his own machine and replace your JavaScript with something else.
Bottom line: JavaScript in browser is client-side. Client can do whatever he pleases with it.
Try doing something like this:
(function(){
//All of your current code
})();
One thing to still be aware of - Chrome developer tools also lets you edit the javascript (not the javascript file on the server, just currently running copy.) Go to Chrome Dev Tools->Sources and you can edit the javascript files.
You can't. Your saying you need to define your map globally, this means it's accessible for everyone.
You could define your map in a different scope and then only define the "public" things:
(function() {
var map = new Map();
window.myMap = {
goTo: function(lat, lng) {
map.goTo(lat, lng);
}
};
})();
Depending on your architecture, there are a few ways to accomplish this. Use this method to create a reusable component that has public and private properties:
var protectedScope = function () {
var protected_var = 'protected';
this.showProtected = function () {
return protected_var;
}
this.public = 'public';
};
var myObject = new protectedScope();
console.log('Public var: '+myObject.public); // outputs "public"
console.log('Protected via accessor: '+myObject.showProtected ()); // outputs "private"
console.log('Protected var: '+myObject.protected); // outputs undefined
Any variable or function declared with a var keyword will be, in effect, private. Any variable or function that uses the this.name mechanism will be "public".
Understand that this structure is not truly public or private, such concepts are not a part of the language. There are still ways to get at those variables, and one can always view source. Just be clear; this is a code organization concept rather than a security concept. Chrome has had this developer console for a while, and other major user agents are moving to include similar tools (or already have done so). There are also tools like Firebug which allow a user full access to your javascript runtime environment. This isn't a realm that the developer can control at all.
Try it here: http://jsfiddle.net/cf2kS/
More Reading
"Private Members in JavaScript" by Douglas Crockford* - http://www.crockford.com/javascript/private.html
"OOP in JS, Part 1 : Public/Private Variables and Methods" on http://phrogz.net - http://phrogz.net/JS/classes/OOPinJS.html
Javascript Object Management on MDN - https://developer.mozilla.org/en-US/docs/XUL_School/JavaScript_Object_Management
Closures on MDN - https://developer.mozilla.org/en-US/docs/JavaScript/Guide/Closures
Object.defineProperty(map, 'zoom', {value:1});
or
Object.defineProperty(map, 'zoom',{
set: function(){console.warn('Access denied!');},
get: function(){return 1;}
});
demo
or
Object.defineProperty(Object.prototype, 'protect', {
value: function(ignore){
var childObjects = [], ignore = ignore || [];
ignore.push(this);
if(this instanceof MimeType)return; //Chrome Fix //window.clientInformation.mimeTypes[0].enabledPlugin[0] !== window.clientInformation.mimeTypes[0]
for(var prop in this){
if(typeof this[prop] === "unknown")continue; //IE fix
if(this[prop] instanceof Object){
var skip = false;
for(var i in ignore)
if(ignore[i]===this[prop]){
skip = true;
break;
}
if(!skip)childObjects.push(prop);
}
var d = Object.getOwnPropertyDescriptor(this, prop);
if(!d || !d.configurable || !d.writable)continue;
var that = this;
(function(){
var temp = that[prop];
delete that[prop];
Object.defineProperty(that, prop,{
set: function(){console.warn('Access denied!');},
get: function(){return temp;}
});
})();
}
for(var i = 0;i<childObjects.length;i++)
this[childObjects[i]].protect(ignore);
}
});
this.onload=function(){this.protect();} //example
demo