Reputation: 528
So I tried to include threejs as a drop-in script into my code. No webpack, no browserify, no requirejs. Just a simple gulp/browsersync serve. I load an external angular app and extend it. Now I need my own THREEjs Version within the codebase.
It gets loaded - but right in the first line they try to set the variable 'global' which doesn't seem to be defined. What am I missing?
// edit:
I am using a js api from another company. I don't know if they set the 'global' var, but Threejs definitely tries to use the var 'global' although I don't use it in a node setup. but in all examples it just works as a drop-in script.
If I use the minified version the error changes to
TypeError: global is undefined *three.min.js:2:168
anonymous https://localhost:9000/scripts/three.min.js:2:168
anonymous https://localhost:9000/scripts/three.min.js:2:2*
and this originates from the following first lines of the three.js file:
function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(factory((global.THREE = {}))); }(this, (function (exports) { 'use strict'; ...
//EDIT 2:
I finally maaged to find the error which is causing all this. if youre using gulp-babel and include scripts with that snippet on top, babel tries to replace THIS with the current context, which is - of course - undefined. and thats why bable literally replaces this with undefined. so: never babel() your final vendor files!
Upvotes: 1
Views: 2195
Reputation: 6553
Since "just getting babel to ignore certain files" is by no means trivial when working in gulp, a quick and dirty fix for this error is to swap this
with window
on the 5th line of three.js
:
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(factory((global.THREE = {})));
}(window, (function (exports) { 'use strict';
Upvotes: 0
Reputation: 151461
The part of THREE.js that you show in your question is not a problem. If we focus only on the problem you've been having, and eliminate the code for the CommonJS and AMD cases, it boils down to this:
(function (global, factory) {
factory(global.THREE = {});
}(this, (function (exports) { 'use strict';
// ...
})));
This is a common pattern. Note that the first anonymous function is called with this
as the first argument. So global
is set to the value that this
has in the global space. If the code above executes in a top-level execution context, then this
will automatically have the value of the global object for the environment in which you run the code. In Node, that object is named global
. So open a Node session and type:
global === this
You'll get true
. In a browser the global object is named window
. Open the console in debugging and type:
window === this
You'll get true
. So what the code snippet with the anonymous function does is that it uses this
to grab a reference to the global object irrespective of where the code executes. It does not have to check whether window
exits or global
exist, or self
or anything else. Instead, it just passes this
to the anonymous function and, this way, automatically gets a reference to the global object. There's nothing wrong with that method. It is super common and generally works.
However, it is possible to prevent the code from working properly. For instance if the code above is wrapped in another function and that function uses "use strict", then this
will be undefined, and global
will be undefined too. Here's an example:
(function() {
"use strict";
(function(global, factory) {
console.log("XXX", global); // You'll get "XXX undefined" here
}(this, (function(exports) {
'use strict';
})));
}());
Sometimes, build processes or code loading tools add such wrapping code, and then they mess up the original code.
Upvotes: 3
Reputation: 477
Is this what you need? Just add this one-liner at the very head of your code, in the global scope:
if (typeof global === "undefined"){global=window;}
This is going to reference the global
object to the window
object, which is the object containing all global variables in browser.
Upvotes: -1