I don't know if this is IDE related, or purely about the transpiling process.
I use Webstorm on a mac, and have node,npm and coffeescript installed. The IDE is using that to make the transpiling to javascript:
//Coffeescript code, simple variable declaration
myamount = 56
//Traspiled javascript generated by CoffeeScript 1.6.3
(function() {
var myamount;
myamount = 5;
}).call(this);
Any clue why it puts the variable in anonymous function ? This is not correct transpiling.
That is to prevent you from polluting the global namespace.
As explained in the documentation - lexical scope and variable safety:
all CoffeeScript output is wrapped in an anonymous function:
(function(){ ... })(); This safety wrapper, combined with the
automatic generation of the var keyword, make it exceedingly difficult
to pollute the global namespace by accident.
Related
What diff between babel-polyfill and babel-es2015? Does babel-es2015 include the babel-polyfill?
Babel-polyfill
This module accomplishes emulating ES2015 by assigning methods on the global (like: Promise and WeakMap) and to prototypes (like Array.prototype.includes). For example: if your environment doesn’t have a Promise object, once you require babel-polyfill, you know have the Promise object, because it was added to the global scope.
Babel-runtime
This module does something very similar, but it doesn’t change the global namespace or pollute prototypes. Instead, babel-runtime can be included as a dependency of your application, just like any other module, and you can include the ES2015 method from the module.
For example: the Promise object, can be included by using:
include-promise
require('babel-runtime/core-js/promise');
This however, is too much work, so we use babel-plugin-transform-runtime which we can add to our babel config to automatically rewrite your code such that you write your code using the Promise API and it will be transformed to use the Promise-like object exported by babel-runtime.
babel-config
{
"plugins": ["transform-runtime"]
}
more details can find here
So when to use what?
If you don’t care about polluting the global scope, babel-polyfill is
the better option: the runtime does not work with instance methods
such as myArray.includes(15).
If you are writing a public module: use babel-runtime
If you are writing an app then babel-polyfill is the better option
There will be cases, when you don’t need either of these, if you’re
writing a library where size matters, you may be better of avoiding
them.
While using ReasonML and Bucklescript, is it possible to configure Bucklescript so it won't generate export statements? I'd prefer if the generated code could be used as is in a browser, that is, being ES5 (or ES6) compatible.
Edit: OK, while trying out the tool chain a bit more, I realize just turning off the export is not enough. See example below:
function foo(x, y) {
return x + y | 0;
}
var Test = /* module */[
/* foo */foo
];
exports.Test = Test;
This code will pollute global namespace if exports is removed, and is simply broken from an ES5 compatibility viewpoint.
Edit 2: Reading on Bucklescript's blog, this seems not possible:
one OCaml module compiled into one JavaScript module (AMDJS, CommonJS, or Google module) without name mangling.
Source.
BuckleScript can output modules in a number of different module formats, which can then be bundled up along with their dependencies using a bundler such as webpack or rollup. The output is not really intended to be used as a stand-alone unit, since you'd be rather limited in what you could do in any case, as the standard and runtime libraries are separate modules. And even something as trivial as multiplication will involve the runtime library.
You can configure BuckleScript to output es6 modules, which can be run directly in the browser as long as your browser supports it. But that would still require manually extracting the standard and runtime libraries from your bs-platform installation.
The module format is configured through the package-specs property in bsconfig.json:
{
...
"packages-specs": ["es6-global"] /* Or "es6" */
}
Having said all that, you actually can turn off exports by putting [###bs.config { no_export }] at the top of the file. But this is undocumented since it's of very limited use in practice, for the above mentioned reasons.
If I install the SassAndCoffee.Core package from NuGet, and then ask SassAndCoffee to compile some CoffeeScript, it seems to pass the "bare" option to the CoffeeScript compiler -- i.e., it does not wrap my script in CoffeeScript's usual (function() { and }).call(this); bookends.
Is there a way I can make SassAndCoffee not use the "bare" option?
Note: this is in a desktop app, and I'm explicitly calling into SassAndCoffee's code -- this is not the magic rewriting that happens in an ASP.NET site.
More details: Here's my code to compile CoffeeScript using SassAndCoffee.
var sassCompiler = new CoffeeScriptCompiler();
var js = sassCompiler.Compile("alert 'Hello World'");
which results in the following (bare) output in the js variable:
alert('Hello World');
But if I write some straightforward JavaScript that calls the official CoffeeScript compiler with the default options, e.g. this HTML file (drop coffee-script.js into the same directory):
<script src="coffee-script.js"></script>
<script>
document.write("<pre>")
document.write(CoffeeScript.compile("alert 'Hello World'"))
document.write("</pre>")
</script>
I get the expected, wrapped JavaScript output:
(function() {
alert('Hello World');
}).call(this);
It looks like SassAndCoffee is calling CoffeeScript.compile(input, {bare: true}) instead of just CoffeeScript.compile(input).
I'd like to use SassAndCoffee.Core for its V8 support, but I want to be able to choose between default output and bare output. Short of rewriting SassAndCoffee's CoffeeScript compiler (which would kinda defeat the point of using SassAndCoffee), or manually prepending and appending the wrapper code (I'd feel dirty duplicating work that the compiler is supposed to do), is there any way I can get SassAndCoffee to output non-bare JavaScript?
If I'm reading this right, it seems to be an explicit decision by the developers:
https://github.com/xpaulbettsx/SassAndCoffee/blob/43300b7805db8b3dccf20cc71d1282ecfd8c76e1/SassAndCoffee.Core/CoffeeScript/coffee-script.js
That might also provide you the file you need to change to modify it to your needs.
As an alternative, in case you get stuck, I use Mindscape Web Workbench as a Visual Studio plugin that seems to do most of what it appears SassAndCoffee accomplishes for you.
Working with Rails 3.1 (rc5), and I'm noticing that any coffeescript file I include rails (or sprockets) is adding in initializing javascript at the top and bottom. In other words, a blank .js.coffee file gets outputted looking like this:
(function() {
}).call(this);
This is irritating because it screws up my javascript scope (unless I really don't know what I'm doing). I generally separate all of my javascript classes into separate files and I believe that having that function code wrapping my classes just puts them out of scope from one another. Or, atleast, I can't seem to access them as I am continually getting undefined errors.
Is there a way to override this? It seems like this file in sprockets has to do with adding this code:
https://github.com/sstephenson/sprockets/blob/master/lib/sprockets/jst_processor.rb
I understand that wrapping everything in a function might seem like an added convenience as then nothing is ran until DOM is loaded, but as far as I can tell it just messes up my scope.
Are you intending to put your objects into the global scope? I think CoffeeScript usually wraps code in anonymous functions so that it doesn't accidentally leak variables into the global scope. If there's not a way to turn it off, your best bet would probably be to specifically add anything you want to be in the global scope to the window object:
window.myGlobal = myGlobal;
It seems to be a javascript best practice these days to put code inside a function scope and be explicit about adding objects to the global scope, and it's something I usually see CoffeeScript do automatically.
You don't want to put everything into the global scope. You want a module or module like system where you can namespace things so you don't colide with other libraries. Have a read of
https://github.com/jashkenas/coffee-script/wiki/Easy-modules-with-coffeescript
So I have two controllers, hotels and videos. I want the hotels.js.coffee to be able to access functions created in videos.js.coffee but I get a "is not defined" error.
I'm new to CoffeeScript so any clues would be appreciated.
CoffeeScript will compile your coffee to JS wrapped in a self-executing function with the scope of the window (function{}).call(this);
So in videos.js.coffee you can write something like:
#getVideo: (id) ->
and the getVideo function will be bound to the window object.
CoffeScript runs inside an anonymous function, so declared funcitons in the same file, aren't exported as global functions.
Try something like this to declare global functions:
window.myFunction = ->
//some code
During compilation, CoffeeScript wraps your code in an anonymous function and applies it. You have to export your public interface in the expected manner for your environment.
(exports || window).publicMethod = (foo, bar) -> foo + bar
You then require using require() in node.js and by referencing the window object in the browser.
There are other ways to do this in the browser. Look into RequireJS.
Indeed you can use either the top-level window variable, or the exports object provide through CommonJS. Please note, you can also give access to complete controllers instead of just functions.
See the sections 'Lexical Scoping and Variable Safety' and '"text/coffeescript" Script Tags' at http://jashkenas.github.com/coffee-script/.