Terminology: types, constructors, classes, …
Ah, now I see the impetus for your other question (that's what I get for reading out of order).
I've had some similar questions recently and found myself deep in the rabbit hole of type theory...and I still don't have a crystal clear answer understanding. I'll take a swing below but take with an appropriately sized grain of salt...
On Sun, Oct 23, 2011 at 2:07 AM, Axel Rauschmayer <axel at rauschma.de> wrote:
Sorry for bringing this up again, but I’m still having trouble with naming things properly in JavaScript.
- What do you call something that produces instances in JavaScript? A class? A type? A constructor? Or is a constructor the implementation of a type?
A constructor is a special kind of function in the language which produces instances of a given type, but you don't necessarily need a constructor to create an instance of a type -- at least w/ the nonstandard proto. Any time you instantiate an object with a specific prototype you've create an instance of a type.
- Are Date and RegExp built-in types? What do you call the value of the global variable Date? Is new Date() an instance of a type or an instance of a constructor?
Date is a type with a constructor. That which is returned by invoking the constructor is an instance of the Date type.
- What about primitives?Are there primitive types and object types? Is the union of the two called just “types”?
That seems to be how a lot of folks refer to them, but I think it's a little confusing. A primitive type is one that cannot be decomposed any further, so Object is a primitive type, and a Function is an object type. I've seen various terminology for the idea I think you're describing: datatype vs. compound type (IEC_11404), or simple type vs. complex type (XSD). But there's a whole lot of very related concepts. I've seen value type used on this list to describe simple primitives, which makes sense to me. The only thing I am sure of is that "typeof" is unfortunately named :)
- If instance factory B inherits from instance factory A, is B a subclass of A? B a subtype of A? B a subconstructor of A?
There's no formal notion of a factory in the language, just a pattern. So none of the above? But if factory B returns instanceof B types, which are instanceof A, then B is a subtype of A. You could also call this a subclass relation, and people often do. This is fine currently as there's no formal notion of classes but might be confusing down the road -- this relationship may be declaratively expressed in a class hierarchy, or it might not, but it's essence would still be characterized by a link in a proto chain.
There's a lot more to it formally, but javascript's type system -- the extensible bits available to us devs at least -- is limited to prototypes. Fundamentally, the ideas of value spaces, co and contravariance, Liskov Substitutability are all plenty relevant, you're pretty much on your own for enforcement. You could also say javascript's type lattice is pretty damn degenerate. This isn't a complaint though, just an observation -- I haven't heard too many people clamoring for static typing :)
(I do think structural typing could be really useful but I have no idea how it could be introduced to the language unobtrusively.)
- Does a class literal (if it makes it into ES.next) define a class? Is a class the implementation of a type?
My guess is a class literal would define a class -- anything else would be too confusing. But classes will never be the only game in town in defining the prototype hierarchy.
On Sun, Oct 23, 2011 at 3:07 AM, Axel Rauschmayer <axel at rauschma.de> wrote:
- What do you call something that produces instances in JavaScript? A class? A type? A constructor? Or is a constructor the implementation of a type?
At least in my part of the everyday life of a JavaScript programmer, we call functions that we invoke with "new" mostly "classes" and sometimes "constructors". In contrast, values not objects are the ones that have types (only boolean, number and string) even if values in JS are indeed objects.
- If instance factory B inherits from instance factory A, is B a subclass of A? B a subtype of A? B a subconstructor of A?
We say it's a subclass, but we mostly say "inherits from".
Juan
- What do you call something that produces instances in JavaScript? A class? A type? A constructor? Or is a constructor the implementation of a type?
At least in my part of the everyday life of a JavaScript programmer, we call functions that we invoke with "new" mostly "classes" and sometimes "constructors". In contrast, values not objects are the ones that have types (only boolean, number and string) even if values in JS are indeed objects.
- If instance factory B inherits from instance factory A, is B a subclass of A? B a subtype of A? B a subconstructor of A?
We say it's a subclass, but we mostly say "inherits from".
How about this (expanding your proposal)?
- Every value in JavaScript is an element (not an instance!) of a type.
- There are primitive types and object types.
- Object types are implemented via constructors/classes.
- A class/constructor produces objects that are its instances.
- A constructor inherits from another constructor.
- A class is a subclass of another class.
I wonder if the word class couldn’t be avoided (certainly not with class literals).
- What about primitives?Are there primitive types and object types? Is the union of the two called just “types”?
That seems to be how a lot of folks refer to them, but I think it's a little confusing. A primitive type is one that cannot be decomposed any further, so Object is a primitive type, and a Function is an object type.
Almost: a primitive is something that isn’t handled by reference. Object is therefore not a primitive type: var o1 = new Object(); var o2 = o1; o1.foo = 123; console.log(o2.foo); // 123
www.2ality.com/2011/03/javascript-values-not-everything-is.html
The only thing I am sure of is that "typeof" is unfortunately named :)
I now use the rule of thumb:
- typeof: use for primitives and to distinguish primitives from objects.
- instanceof: use for objects.
Obviously, typeof also works for checking for functions.
You could also say javascript's type lattice is pretty damn degenerate.
Can you elaborate?
(I do think structural typing could be really useful but I have no idea how it could be introduced to the language unobtrusively.)
Something like this? var Counter = { inc: "function", data: "number" }; matchesInterface(anObject, Counter);
On Sun, Oct 23, 2011 at 12:01 PM, Axel Rauschmayer <axel at rauschma.de> wrote:
- What about primitives?Are there primitive types and object types? Is the
union of the two called just “types”?
That seems to be how a lot of folks refer to them, but I think it's a little confusing. A primitive type is one that cannot be decomposed any further, so Object is a primitive type, and a Function is an object type.
Almost: a primitive is something that isn’t handled by reference. Object is therefore not a primitive type: var o1 = new Object(); var o2 = o1; o1.foo = 123; console.log(o2.foo); // 123
www.2ality.com/2011/03/javascript-values-not-everything-is.html
Is that from the spec? My interpretation of "primitive" is from ISO/IEC 11404 (a surprisingly good read for a spec about types!): primitive datatypes are "defined axiomatically without reference to other datatypes" and goes on to say "All primitive datatypes are conceptually atomic". XSD similarly defines primitives: "Primitive datatypes are those that are not defined in terms of other datatypes; they exist ab initio."
What you're defining as primitive is instead the notion of value types, but it's all kind of jumbled together anyway. To my mind the notion of value vs. reference types are completely orthagonal, and instead closely related to mutability. Still, I agree I was wrong to call Objects primitive -- Object instances are still derived, or generated, or compound, or product, or whatever (AFAICT the literature is all over the map on this).
The only thing I am sure of is that "typeof" is unfortunately named :)
I now use the rule of thumb:
- typeof: use for primitives and to distinguish primitives from objects.
I'd point out the failure of "null" here but that's being fixed. But your comments help demonstrate my point, that javascript's type system is bifurcated.
- instanceof: use for objects.
It's usable on objects, but not all that useful, even with natives like Array (they could have come from another frame). This is my biggest problem with javascript's nominative types. Ducktyping helps, but meh. This is one reason I'm so excited about private names and the de jure namespace the module system gives us -- which can help sort this out once and for all.
Obviously, typeof also works for checking for functions.
You could also say javascript's type lattice is pretty damn degenerate.
Can you elaborate?
The subtype relation is a partial order -- whether the top and bottom type are implicit or explicit is language dependent, but as a partial order all types in a given system can be represented as a lattice. But if you drew the types of any es5 application as a hasse diagram it would look pretty goofy -- flat on one side with most of the built-ins nearly impossible to extend, and then below Object you'd have a tree that sprawls out, with each leaf bottoming out at falsum. So that's what I meant by a degenerate lattice. And es-next does offer some help with extending the built-ins, it's type system will still lack the capabilities to do much else, like derivation by restriction.
This is all just speaking to the built-in type system -- obviously any number of application-level type systems have been layered on top with various characteristics. This is another problem :-/
(I do think structural typing could be really useful but I have no idea how it could be introduced to the language unobtrusively.)
Something like this? var Counter = { inc: "function", data: "number" }; matchesInterface(anObject, Counter);
You could do that and more with a library today, but you'd just be layering on third incompatible type system. And then we'd have three problems :)
On 23.10.2011 10:07, Axel Rauschmayer wrote:
Sorry for bringing this up again, but I’m still having trouble with naming things properly in JavaScript.
- What do you call something that produces instances in JavaScript? A class? A type? A constructor? Or is a constructor the implementation of a type?
In ES spec it's called precisely and exactly -- it's a constructor.
In contrast with other languages (usually with strong and static typing), in ES a concept of a "class" doesn't reflect the concept of a "type".
Thus, the "statics" vs. "dynamics" doesn't cancel the fact that a "class" can be equivalent of a "type" -- e.g. in Python, classes are first-class, but they are "types":
class A(object): pass
a = A() type(a) # class A
type(a) == a.class # true
The same picture can be seen in other languages (Java, C++, etc).
In JS an "entity" which generates instances isn't the class of the instances. This entity (once again, and that is mentioned in the spec) is called a constructor.
However, if you consider some generic aspects of computer science, then a pair of constructor function + prototype may be called a "class", since the work of class is (1) to generate instances by a template and (2) hierarchical (vertical) code reuse which is called inheritance. Constructor function + prototype pair does exactly this in ES. So it's a "class" (and can be syntactically sugared as in CoffeeScript and Python; yes, Python is delegation-based and classes there are just the same syntactic sugar). More precisely -- a "dynamic first-class class" (for more info on types of classes, see this: gist.github.com/977034)
So if you want to talk in borders of ES, call it constructor. If you call abstractly at comp.sci level, you may call it class. But in contrast with other langs to which you used to, a class here isn't a type.
- Are Date and RegExp built-in types? What do you call the value of the global variable Date? Is new Date() an instance of a type or an instance of a constructor?
Precisely Date and RegExps are constructors which generate instances of the Object type (don't confuse with the Object constructor!). You may call it (unofficially) sub-types of Object type.
An instance of a constructor. And all instances are of type of Object.
- What about primitives?Are there primitive types and object types?
Please read this one completely to cover these questions in detail and completely: dmitrysoshnikov.com/ecmascript/chapter-7-2-oop-ecmascript-implementation
There is only one object type and it's called Object type. All the other
types (excluding internal) are primitive types. A value gets the Object
type when is created by any constructor. After that you may distinguish
these values (which all have the Object type) only by analyzing
prototype chain (via instanceof operator) or by testing
"classification-tag" -- the inherited property constructor
or (for
standard "classes") by testing "classification-tag" -- the internal
property [[Class]], which though is planned (by Allen) to be removed
from the spec.
Is the union of the two called just “types”?
In comp.sci it's called a class which may be an equivalence of a type. Here two instances are just objects which were created by some constructor and, once again, can the same type Object. But, may have different prototype chain and classification-tags.
- If instance factory B inherits from instance factory A, is B a subclass of A? B a subtype of A? B a subconstructor of A?
Your assumption points that you very likely mostly programed before in static systems (such as Java, etc). Please refer this info to cover the topic completely: dmitrysoshnikov.com/ecmascript/chapter-7-1-oop-general-theory
In ES, a "factory B" doesn't inherit from "factory A". Here only objects inherit from their prototype chains. A "factory A" inherits from its prototype chain (usually Function.prototype).
If you though want to use concept of a class and create a useful sugar (class system) for it and build your system using classes, then yes, you may say that class B inherits from class A -- and it will be correct an this abstraction level. In practice (i.e. on lower abstraction level), it will just mean that an object created by the constructor B inherits from the prototype which in turn inherits from the A.prototype.
- Does a class literal (if it makes it into ES.next) define a class? Is a class the implementation of a type?
No, in current ES type system a class will not define a type. However it can be fixed (e.g. to set [[Class]] property to constructor name and to take into account typeof operator). In ES, classes are just sugar for proto-based inheritance. The same as in Coffee, the same as in Python.
Intuitively, it is clear how things work, but I find it difficult to be precise when talking/writing about them.
Hope it helped.
More info you'll find again in the literature I gave above and in the spec (after reading the spec there will be no questions such as "is class is the type in ES?").
Dmitry.
Almost: a primitive is something that isn’t handled by reference.
Is that from the spec? My interpretation of "primitive" is from ISO/IEC 11404 (a surprisingly good read for a spec about types!): primitive datatypes are "defined axiomatically without reference to other datatypes" and goes on to say "All primitive datatypes are conceptually atomic". XSD similarly defines primitives: "Primitive datatypes are those that are not defined in terms of other datatypes; they exist ab initio."
What you're defining as primitive is instead the notion of value types, but it's all kind of jumbled together anyway. To my mind the notion of value vs. reference types are completely orthagonal, and instead closely related to mutability. Still, I agree I was wrong to call Objects primitive -- Object instances are still derived, or generated, or compound, or product, or whatever (AFAICT the literature is all over the map on this).
Every language defines "primitive" different, you thus have to be careful with transferring these concepts. The spec elegantly avoids the issue by simply enumerating which types are primitive.
The best you can do, then, is to describe how primitives work. Possibly like this:
Primitives are immutable value types. Any properties they have, they get from their object wrapper types. I think strings get their "length" property this way, too – I think it is often implemented as a getter that accesses an internal property that strings have.
But your comments help demonstrate my point, that javascript's type system is bifurcated.
True, but I think it works well – primitives supported by object wrapper types.
- instanceof: use for objects.
It's usable on objects, but not all that useful, even with natives like Array (they could have come from another frame). This is my biggest problem with javascript's nominative types. Ducktyping helps, but meh. This is one reason I'm so excited about private names and the de jure namespace the module system gives us -- which can help sort this out once and for all.
Both are indeed welcome. I wonder how often the frame crossing is an issue in practice.
You could also say javascript's type lattice is pretty damn degenerate.
Can you elaborate?
The subtype relation is a partial order -- whether the top and bottom type are implicit or explicit is language dependent, but as a partial order all types in a given system can be represented as a lattice. But if you drew the types of any es5 application as a hasse diagram it would look pretty goofy -- flat on one side with most of the built-ins nearly impossible to extend, and then below Object you'd have a tree that sprawls out, with each leaf bottoming out at falsum. So that's what I meant by a degenerate lattice. And es-next does offer some help with extending the built-ins, it's type system will still lack the capabilities to do much else, like derivation by restriction.
This is all just speaking to the built-in type system -- obviously any number of application-level type systems have been layered on top with various characteristics. This is another problem :-/
I find things is JavaScript much more workable than in Java. A few minor quirks need to be fixed, but I don’t have any major complaints (I’m not very demanding in this area). Ignoring aesthetic objections – what problems can’t you solve in JavaScript now?
(I do think structural typing could be really useful but I have no idea how it could be introduced to the language unobtrusively.)
Something like this? var Counter = { inc: "function", data: "number" }; matchesInterface(anObject, Counter);
You could do that and more with a library today, but you'd just be layering on third incompatible type system. And then we'd have three problems :)
I don’t think it clashes with what is there, it’s more like a helper for duck typing.
Most of the answers below are direct quotes from ES 5.1
- What do you call something that produces instances in JavaScript? A class? A type? A constructor? Or is a constructor the implementation of a type?
A constructor. es5.github.com/#x4.3
- Are Date and RegExp built-in types? What do you call the value of the global variable Date? Is new Date() an instance of a type or an instance of a constructor?
These are constructor properties of the global object. es5.github.com/#x15.1.4
When Date is called as part of a new expression, it is a constructor: it initialises the newly created object. es5.github.com/#x15.9.3
- What about primitives?Are there primitive types and object types? Is the union of the two called just “types”?
A member of one of the types Undefined, Null, Boolean, Number, or String es5.github.com/#x4.3.2 Everything else is an object.
- If instance factory B inherits from instance factory A, is B a subclass of A? B a subtype of A? B a subconstructor of A?
B inherits A's prototype, A is in B's "prototype chain"
- Does a class literal (if it makes it into ES.next) define a class? Is a class the implementation of a type?
I can't answer this
Thanks for your thorough answer!
- If instance factory B inherits from instance factory A, is B a subclass of A? B a subtype of A? B a subconstructor of A?
Your assumption points that you very likely mostly programed before in static systems (such as Java, etc). Please refer this info to cover the topic completely: dmitrysoshnikov.com/ecmascript/chapter-7-1-oop-general-theory
In ES, a "factory B" doesn't inherit from "factory A". Here only objects inherit from their prototype chains. A "factory A" inherits from its prototype chain (usually Function.prototype).
If you though want to use concept of a class and create a useful sugar (class system) for it and build your system using classes, then yes, you may say that class B inherits from class A -- and it will be correct an this abstraction level. In practice (i.e. on lower abstraction level), it will just mean that an object created by the constructor B inherits from the prototype which in turn inherits from the A.prototype.
I do understand all that! But the fact is that there are many functions like Node.js util.inherits() out there that make it seem like you can let one constructor inherit from another one. I’m just looking for the right words to express what is happening in such a case.
On Sun, Oct 23, 2011 at 11:11 AM, Axel Rauschmayer <axel at rauschma.de> wrote:
- instanceof: use for objects.
It's usable on objects, but not all that useful, even with natives like Array (they could have come from another frame). This is my biggest problem with javascript's nominative types. Ducktyping helps, but meh. This is one reason I'm so excited about private names and the de jure namespace the module system gives us -- which can help sort this out once and for all.
Both are indeed welcome. I wonder how often the frame crossing is an issue in practice.
If you control all of the code and like a constrained style, use instanceof. For robust code use instanceof only for RHS in the same library. Every time I write 'instanceof' I flinch from past surprises, cross frame, objects that should say true but don't (structurally true), objects that should say false but don't (monkey patched).
jjb
- What about primitives?Are there primitive types and object types? Is the union of the two called just “types”?
A member of one of the types Undefined, Null, Boolean, Number, or String es5.github.com/#x4.3.2 Everything else is an object.
Yes that is probably the most elegant way of defining the term. Afterwards, one can go on and describe how primitives work.
- If instance factory B inherits from instance factory A, is B a subclass of A? B a subtype of A? B a subconstructor of A?
B inherits A's prototype, A is in B's "prototype chain"
B.prototype inherits A.protoype. A.prototype is a prototype of B. prototype (ugh).
On Sun, Oct 23, 2011 at 11:24 AM, Axel Rauschmayer <axel at rauschma.de> wrote:
- If instance factory B inherits from instance factory A, is B a subclass
of A? B a subtype of A? B a subconstructor of A?
B inherits A's prototype, A is in B's "prototype chain"
B.prototype inherits A.protoype. A.prototype is a prototype of B. prototype (ugh).
This kind of nonsense is why I like the 'selfish' model. The prototype chain consists of plain objects with behaviors as properties. So you just say A is a prototype of B. (I guess you are trying terminology for all of JS, but your example points out one of the issues with new/fnc.prototype solution).
jjb
- If instance factory B inherits from instance factory A, is B a subclass of A? B a subtype of A? B a subconstructor of A?
B inherits A's prototype, A is in B's "prototype chain"
B.prototype inherits A.protoype. A.prototype is a prototype of B. prototype (ugh).
This kind of nonsense is why I like the 'selfish' model. The prototype chain consists of plain objects with behaviors as properties. So you just say A is a prototype of B. (I guess you are trying terminology for all of JS, but your example points out one of the issues with new/fnc.prototype solution).
Agreed.
FWIW: I’ve implemented something similar to Selfish (using the method "new" was inspired by it): rauschma/proto
I believe the community just says A inherits B even thought they mean that A.prototype.[[Prototype]] == B.prototype.
On Oct 23, 2011 7:24 PM, "Axel Rauschmayer" <axel at rauschma.de> wrote:
- What about primitives?Are there primitive types and object types? Is
the union of the two calle... Yes that is probably the most elegant way of defining the term. Afterwards, one can go on and describe how primitives work.
- If instance factory B inherits from instance factory A, is B a subclass
of A? B a subtype of ... B.prototype inherits A.protoype. A.prototype is a prototype of B. prototype (ugh).
-- Dr. Axel Rauschmayer axel at rauschma.de home: rauschma.de twitter: twitter.com/rauschma blog: 2al...
Does no one read RPG's fine Clause 3 of ECMA-262 these days?
Can you elaborate? It seems like a cultural reference, but I don’t get it.
On Oct 23, 2011, at 3:27 PM, Axel Rauschmayer wrote:
Can you elaborate? It seems like a cultural reference, but I don’t get it.
On Oct 24, 2011, at 0:18 , Brendan Eich wrote:
Does no one read RPG's fine Clause 3 of ECMA-262 these days?
Sorry, Clause 4. That's "Section 4" or "Chapter 4" to most of us. RPG = Richard P. Gabriel, who drafted this section. Here's the start of 4.2:
4.2 Language Overview
The following is an informal overview of ECMAScript—not all parts of the language are described. This overview is not part of the standard proper.
ECMAScript is object-based: basic language and host facilities are provided by objects, and an ECMAScript program is a cluster of communicating objects. An ECMAScript object is a collection of properties each with zero or more attributes that determine how each property can be used—for example, when the Writable attribute for a property is set to false, any attempt by executed ECMAScript code to change the value of the property fails. Properties are containers that hold other objects, primitive values, or functions. A primitive value is a member of one of the following built-in types: Undefined, Null, Boolean, Number, and String; an object is a member of the remaining built-in type Object; and a function is a callable object. A function that is associated with an object via a property is a method.
ECMAScript defines a collection of built-in objects that round out the definition of ECMAScript entities. These built-in objects include the global object, the Object object, the Function object, the Array object, the String object, the Boolean object, the Number object, the Math object, the Date object, the RegExp object, the JSON object, and the Error objects Error, EvalError, RangeError, ReferenceError, SyntaxError, TypeError and URIError.
ECMAScript also defines a set of built-in operators. ECMAScript operators ... --- end snip ---
Chapter 8 defines what the ecma-262 spec means by "type".
Sent from Samsung tablet
Sorry for bringing this up again, but I’m still having trouble with naming things properly in JavaScript.
What do you call something that produces instances in JavaScript? A class? A type? A constructor? Or is a constructor the implementation of a type?
Are Date and RegExp built-in types? What do you call the value of the global variable Date? Is new Date() an instance of a type or an instance of a constructor?
What about primitives?Are there primitive types and object types? Is the union of the two called just “types”?
If instance factory B inherits from instance factory A, is B a subclass of A? B a subtype of A? B a subconstructor of A?
Does a class literal (if it makes it into ES.next) define a class? Is a class the implementation of a type?
Intuitively, it is clear how things work, but I find it difficult to be precise when talking/writing about them.