UnityScript versus JavaScript

From Unify Community Wiki
(Difference between revisions)
Jump to: navigation, search
(Removed outdated info)
m (Text replace - "<javascript>" to "<syntaxhighlight lang="javascript">")
Line 8: Line 8:
  
 
JavaScript has no classes. This is because it's a prototypal language, and not a classical one. Inheritance happens with [more dynamic] objects, rather than [unchanging] classes.
 
JavaScript has no classes. This is because it's a prototypal language, and not a classical one. Inheritance happens with [more dynamic] objects, rather than [unchanging] classes.
<javascript>function Machine(x) {
+
<syntaxhighlight lang="javascript">function Machine(x) {
 
   this.kind = ["bulldozer", "lathe", "car"][x];
 
   this.kind = ["bulldozer", "lathe", "car"][x];
 
}
 
}
Line 26: Line 26:
 
UnityScript has classes, and functions cannot create objects as in JavaScript. Extension is therefore impossible. However, there is the added benefit of being an easier-to-read, more familiar (to most) language.
 
UnityScript has classes, and functions cannot create objects as in JavaScript. Extension is therefore impossible. However, there is the added benefit of being an easier-to-read, more familiar (to most) language.
  
<!--<unityscript--><javascript>class Machine {
+
<!--<unityscript--><syntaxhighlight lang="javascript">class Machine {
 
   var kind : String;
 
   var kind : String;
 
   function Machine(x : int) {
 
   function Machine(x : int) {
Line 45: Line 45:
  
 
JavaScript supports multiple variable declarations in one <code>var</code> statement.
 
JavaScript supports multiple variable declarations in one <code>var</code> statement.
<javascript>var x = 3, y = 4;</javascript>
+
<syntaxhighlight lang="javascript">var x = 3, y = 4;</javascript>
 
UnityScript does not.
 
UnityScript does not.
  
Line 52: Line 52:
 
In JavaScript, assignment is treated as an expression.
 
In JavaScript, assignment is treated as an expression.
  
<javascript>var x = 3; // x is 3
+
<syntaxhighlight lang="javascript">var x = 3; // x is 3
 
var y = (x=x+2); // x is 5, y is 5</javascript>
 
var y = (x=x+2); // x is 5, y is 5</javascript>
  
 
In Unity, assignment is always a statement, so this must be broken up into steps.
 
In Unity, assignment is always a statement, so this must be broken up into steps.
<javascript>var x = 3; // x is 3
+
<syntaxhighlight lang="javascript">var x = 3; // x is 3
 
   // var y = (x=x+2); // Error!
 
   // var y = (x=x+2); // Error!
 
x = x + 2; // x is 5
 
x = x + 2; // x is 5
Line 62: Line 62:
  
 
The exceptions are the [pre/post]-[in/de]crement operations:
 
The exceptions are the [pre/post]-[in/de]crement operations:
<javascript>var x = 3;
+
<syntaxhighlight lang="javascript">var x = 3;
 
var y = x++; // x is 4, y is 3
 
var y = x++; // x is 4, y is 3
  
Line 77: Line 77:
  
 
This code is valid in both UnityScript and JavaScript:
 
This code is valid in both UnityScript and JavaScript:
<javascript>var x;
+
<syntaxhighlight lang="javascript">var x;
 
x = 3;</javascript>
 
x = 3;</javascript>
 
However, it is inefficient in UnityScript because it causes x to be dynamically typed. For faster runtime execution, use one of the two static typing syntaxes.
 
However, it is inefficient in UnityScript because it causes x to be dynamically typed. For faster runtime execution, use one of the two static typing syntaxes.
<javascript>var x = 3; // type `int` is inferred, typed statically</javascript>
+
<syntaxhighlight lang="javascript">var x = 3; // type `int` is inferred, typed statically</javascript>
  
<javascript>var x : int; // typed statically
+
<syntaxhighlight lang="javascript">var x : int; // typed statically
 
x = 3;</javascript>
 
x = 3;</javascript>
  
Line 89: Line 89:
 
In JavaScript, privacy is rather unconventional.
 
In JavaScript, privacy is rather unconventional.
  
<javascript>function Person() { // (this is the *JavaScript* way of doing privacy)
+
<syntaxhighlight lang="javascript">function Person() { // (this is the *JavaScript* way of doing privacy)
 
   var secret = "I am a mass murderer."; // private
 
   var secret = "I am a mass murderer."; // private
 
   this.speak = function() { print("Don't make me tell you my secret! "+secret); }; // prints secret
 
   this.speak = function() { print("Don't make me tell you my secret! "+secret); }; // prints secret
Line 99: Line 99:
 
In UnityScript, it can be more intuitive.
 
In UnityScript, it can be more intuitive.
  
<!--<unityscript>--><javascript>class Person { // UnityScript only; impossible in JavaScript
+
<!--<unityscript>--><syntaxhighlight lang="javascript">class Person { // UnityScript only; impossible in JavaScript
 
   private var secret : String;
 
   private var secret : String;
 
   function Person() {
 
   function Person() {
Line 117: Line 117:
 
Dollar signs ($) are not allowed in UnityScript identifiers as they are in JS identifiers. (In JS, the symbol is often used for c-style namespacing or as the name of a do-everything function.)
 
Dollar signs ($) are not allowed in UnityScript identifiers as they are in JS identifiers. (In JS, the symbol is often used for c-style namespacing or as the name of a do-everything function.)
  
<javascript>var lib$cosine = 3; // ERROR! in UnityScript</javascript>
+
<syntaxhighlight lang="javascript">var lib$cosine = 3; // ERROR! in UnityScript</javascript>
  
 
== No <code>with</code> statement ==
 
== No <code>with</code> statement ==
Line 127: Line 127:
 
In JavaScript (and even JScript.NET, the language on which UnityScript is based), one can directly define a regular expression using a syntax like the following:
 
In JavaScript (and even JScript.NET, the language on which UnityScript is based), one can directly define a regular expression using a syntax like the following:
  
<javascript>var sentence = /[A-Z].*[\.\?!]/; // JavaScript/JScript.NET only</javascript>
+
<syntaxhighlight lang="javascript">var sentence = /[A-Z].*[\.\?!]/; // JavaScript/JScript.NET only</javascript>
  
 
UnityScript does not support this, understandably, as regular expressions are pretty uncommon in game code, and the syntax is hard to tokenize/lex.
 
UnityScript does not support this, understandably, as regular expressions are pretty uncommon in game code, and the syntax is hard to tokenize/lex.
Line 139: Line 139:
 
In UnityScript, as in Oracle/Formerly Sun Java (not JavaScript), only the second of these is true. That is, <code>this</code> will always refer to an instance of an object, specifically the object on which a method is being called.
 
In UnityScript, as in Oracle/Formerly Sun Java (not JavaScript), only the second of these is true. That is, <code>this</code> will always refer to an instance of an object, specifically the object on which a method is being called.
  
<javascript>class Person {
+
<syntaxhighlight lang="javascript">class Person {
 
   var species : String;
 
   var species : String;
 
   var eyeColor : String;
 
   var eyeColor : String;

Revision as of 20:48, 10 January 2012

Though many in the Unity development community (and even in the Unity corporation) refer to UnityScript and JavaScript as if they were equivalent or interchangeable, the two are very different languages. Though they resemble each other syntactically, they have very different semantics.

While "JavaScript" is merely a generic name and could refer to any one of many implementations of the ECMAScript specification, Unity's ".js" language doesn't even come close to conforming to that specification. Most JavaScript libraries you can find will probably not work just by copying them into Unity. If anything, the language is most similar to Microsoft's JScript.NET, although it is not quite identical.

This page attempts to explain the differences between JavaScript (ECMAScript) and UnityScript as succinctly and clearly as possible. If you have any suggestions, feel free to add them to the author's talk page.

JavaScript is class-free

JavaScript has no classes. This is because it's a prototypal language, and not a classical one. Inheritance happens with [more dynamic] objects, rather than [unchanging] classes.

function Machine(x) {
   this.kind = ["bulldozer", "lathe", "car"][x];
}
 
var c = new Machine(2);
print(typeof c.announce); // "undefined"
 
Machine.prototype.announce = function() {
   print("I am a "+this.kind+".");
};
 
print(typeof c.announce); // "function"
c.announce(); // prints "I am a car."</javascript>
 
As shown above, in JavaScript, a function can create an object, when called with the <code>new</code> keyword. After that happens, the prototype (template) object Machine can be extended to provide additional functionality, and all class instances, past and future, are affected by this extension.
 
UnityScript has classes, and functions cannot create objects as in JavaScript. Extension is therefore impossible. However, there is the added benefit of being an easier-to-read, more familiar (to most) language.
 
<!--<unityscript--><syntaxhighlight lang="javascript">class Machine {
   var kind : String;
   function Machine(x : int) {
      this.kind = ["bulldozer", "lathe", "car"][x];
   }
   function announce() {
      print("I am a "+this.kind+".");
   }
}
 
print(typeof Machine.prototype); // undefined
 
var c = new Machine(2);
 
c.announce(); // prints  "I am a car."</javascript><!--</unityscript>-->
 
== One variable declaration at a time ==
 
JavaScript supports multiple variable declarations in one <code>var</code> statement.
<syntaxhighlight lang="javascript">var x = 3, y = 4;</javascript>
UnityScript does not.
 
== Assignment cannot be an expression ==
 
In JavaScript, assignment is treated as an expression.
 
<syntaxhighlight lang="javascript">var x = 3; // x is 3
var y = (x=x+2); // x is 5, y is 5</javascript>
 
In Unity, assignment is always a statement, so this must be broken up into steps.
<syntaxhighlight lang="javascript">var x = 3; // x is 3
  // var y = (x=x+2); // Error!
x = x + 2; // x is 5
var y = x; // y is 5</javascript>
 
The exceptions are the [pre/post]-[in/de]crement operations:
<syntaxhighlight lang="javascript">var x = 3;
var y = x++; // x is 4, y is 3
 
x = 3;
var z = ++x; // x is 4, z is 4</javascript>
 
== No Global Variables ==
 
Every top-level variable in JavaScript is global. Additionally, any variable declaration not preceded by the <code>var</code> statement is global. This is not the case in UnityScript, as every object-owned .js file is essentially wrapped in a <code>class JSFileName extends MonoBehaviour {...}</code> block. The absent-<code>var</code> behavior is avoided by the language prohibiting missing <code>var</code> keywords.
 
By extension, there is no global object, so the <code>this</code> keyword will always point to the innermost object's instance, in contrast to JS's <code>this</code> keyword, which will sometimes point to the global object.
 
== Dynamic typing is inefficient ==
 
This code is valid in both UnityScript and JavaScript:
<syntaxhighlight lang="javascript">var x;
x = 3;</javascript>
However, it is inefficient in UnityScript because it causes x to be dynamically typed. For faster runtime execution, use one of the two static typing syntaxes.
<syntaxhighlight lang="javascript">var x = 3; // type `int` is inferred, typed statically</javascript>
 
<syntaxhighlight lang="javascript">var x : int; // typed statically
x = 3;</javascript>
 
== Privacy ==
 
In JavaScript, privacy is rather unconventional.
 
<syntaxhighlight lang="javascript">function Person() { // (this is the *JavaScript* way of doing privacy)
   var secret = "I am a mass murderer."; // private
   this.speak = function() { print("Don't make me tell you my secret! "+secret); }; // prints secret
}
var bob = new Person();
print(bob.secret); // undefined
bob.speak(); // prints "Don't make me tell you my secret! I am a mass murderer."</javascript>
 
In UnityScript, it can be more intuitive.
 
<!--<unityscript>--><syntaxhighlight lang="javascript">class Person { // UnityScript only; impossible in JavaScript
   private var secret : String;
   function Person() {
      secret = "I am a mass murderer.";
   }
   function speak() {
      print("Don't make me tell you my secret! "+secret);
   }
}
 
var bob = new Person();
print(bob.secret); // undefined
bob.speak(); // prints "Don't make me tell you my secret! I am a mass murderer."</javascript><!--</unityscript>-->
 
== No Bling == 
 
Dollar signs ($) are not allowed in UnityScript identifiers as they are in JS identifiers. (In JS, the symbol is often used for c-style namespacing or as the name of a do-everything function.)
 
<syntaxhighlight lang="javascript">var lib$cosine = 3; // ERROR! in UnityScript</javascript>
 
== No <code>with</code> statement ==
 
There is no <code>with</code> statement in UnityScript. This is probably for the best, as JavaScript's <code>with</code> statement causes the whole language to be slower, regardless of whether the statement is used or not. It is also considered harmful.
 
== No Regular Expression Literals (RegExp or regex) ==
 
In JavaScript (and even JScript.NET, the language on which UnityScript is based), one can directly define a regular expression using a syntax like the following:
 
<syntaxhighlight lang="javascript">var sentence = /[A-Z].*[\.\?!]/; // JavaScript/JScript.NET only</javascript>
 
UnityScript does not support this, understandably, as regular expressions are pretty uncommon in game code, and the syntax is hard to tokenize/lex.
 
== The <code>this</code> keyword ==
 
In JavaScript, <code>this</code> can refer to one of two things, depending on the context:
* The global object (best not explained here)
* The object to which the current method or constructor belongs
 
In UnityScript, as in Oracle/Formerly Sun Java (not JavaScript), only the second of these is true. That is, <code>this</code> will always refer to an instance of an object, specifically the object on which a method is being called.
 
<syntaxhighlight lang="javascript">class Person {
   var species : String;
   var eyeColor : String;
   var hairColor : String;
   function Person(eyeColor : String) {
      species = "homo sapiens";
      this.eyeColor = eyeColor;
      hairColor = "brown";
   }
}</javascript>
 
Note that without the <code>this.</code> qualifier, by default, an identifier (e.g. <code>hairColor</code>) will refer to a class field (<code>this.hairColor</code>) UNLESS a variable of the same name has already been defined (e.g. the argument eyeColor). In such a case, <code>this.</code> must be explicitly included to disambiguate between the variable name and the field (property) name, as seen on line 7 of the code snippet.
Personal tools
Namespaces

Variants
Actions
Navigation
Extras
Toolbox