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!
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.