Type casting in JavaScript - javascript

Example:
function action(value) {
// I want to operate on a string
String(value)...;
}
When we pass dynamic values into JavaScript's primary types (String, Number, Boolean, Object, etc.) we can (for want of a better word) cast the value to the specified type.
Is it possible to build this feature in custom types, and how would I go about this?
Example of what I would like to do:
function action(value) {
Point(value)...;
// Value at this point (excuse the pun) is a point
// // *** Would like to see that intellisense is aware of the type at this point, but please don't assume this is ONLY for intellisense***
}
Is it possible to call constructor functions in this way and have the constructor function "cast" the value to an instance of itself - or does this only work for JavaScript's primary types?

Your custom constructor can just examine the typeof the arguments that it is passed and behave accordingly. This isn't technically a "cast", but rather writing code to examine the types of the arguments and then decide on the proper behavior which can include converting from one type to another.
See How to overload functions in javascript? for a much longer description of how to examine arguments sent to any function and then adjust the behavior of the function based on the type and position and presence of the arguments. This same functionality can be used to do something that is "cast" like (though we don't usually think of casting in Javascript, but rather just converting).
We could give you actual code examples if you can be more specific about what types you want to "cast" in your Point constructor.
There are some simple examples of "cast" like things:
function delay(fn, t) {
// if t is passed as a string represeantation of a number,
// convert it to an actual number
return setTimeout(fn, +t);
}
Or, a little more interesting example that can take a number of ms, a string with units at the end or an object with properties:
function delay(fn, t) {
var typeT = typeof t, ms, matches, num, multiplier,
suffixes = {ms: 1, sec: 1000, min: 1000 * 60, hr: 1000 * 60 * 60};
if (typeT === "string") {
matches = t.match(/^([\d.]+)(.+)$/);
if (matches) {
num = +matches[1];
multiplier = suffixes[matches[2]];
if (multiplier) {
ms = num * multiplier;
}
}
} else if (typeT === "number") {
// plain number is milliseconds
ms = t;
} else if (typeT === "object" && t.units && t.value) {
multiplier = suffixes[t.units];
if (multiplier) {
ms = t.value * multiplier;
}
}
if (ms === undefined) {
throw new Error("Invalid time argument for delay()");
}
return setTimeout(fn, ms);
}
delay(myFn, "2.5hr");
delay(myFn, "25sec");
delay(myFn, 150);
delay(myFn, {units: "sec", value: 25});

If you are serious about type enforcing
(and there is a lot of good reasons to be)...
and you want to continue to use Javascript...
maybe you should give a try to TypeScript
It enforces type checking and compiles down to Javascript
Which gives you the option to publish the TypeScript for inline compilation...
Or if you intent a bit for your work (like me)...
you can develop a project and spit-out the Javascript before uploading... in this phase you can optimize the 'thing'...
pass a Linter, a Minifier and a Obfuscator...
and you'll get highly optimized and a bit protected piece of code (if we are talking about client-side of course, at server side no obfuscation is advised).
Another BIG-BIG-BIG advantage (to me at least) is that you can use the best Intellitype/Intellisense/Refactor IDE (VS 2013R4 CE) which is free.
See here the last features in TypeScript...
TypeScript at Build/2014 by Anders Hejlsberg (channel9)
ZEE

Related

Add attribute to instance of "Number"

I want to see if a number is a multiple of π. So ideally it would behave exactly like an ordinary number, but with extra functionality:
>>> pi
3.14...
>>> pi.isMultipleOfPi
true
>>> b = pi * 5
>>> b.isMultipleOfPi
true
With wishful thinking
>>> c = pi + 1
>>> c.isMultipleOfPi
false
>>> d = pi + 2 * pi
>>> d.isMultipleOfPi
true
Is there a way to achieve something like that in Javascript? I think this would be pretty straight forward in Python, but there seems to be no way to create overloads for addition/multiplication etc. in JS. If there were, I could simply extent the Number class.
Setting something on Number.prototype = function also doesn't seem to work as it sets it for the entire class and not on an instance.
I thought at first you wanted to do this for all numbers, which is answered here.
But if you only want to do this for one specific number, you can, but you probably won't want to. 99.9999999999998% of all numbers you work with in JavaScript are primitives, not objects, and so they don't have any properties (the ones they seem to have only come from Number.prototype [or, in turn, from Object.primitive], which the JavaScript engine will use if you try to access a property on a number primitive).
You could make a number object instead, and put the property on that:
const c = new Number(Math.PI);
c.isMultipleOfPI = true;
console.log(c);
console.log(String(c));
console.log(c.isMultipleOfPI);
The problem with that, though, is demonstrated by the console.log(c); line above. With Chrome's devtools (and perhaps others), you see this:
{
isMultipleOfPI: true,
}
rather than 3.141592653589793 as you might be expecting.
The reason is that c is an object, not a primitive, and some things that use it (such as console.log) may treat it primarily as an object rather than primarily as a number.
Math and string concatenation work, though:
const c = new Number(Math.PI);
c.isMultipleOfPI = true;
console.log(c * 2);
console.log(c - 2);
console.log(c + 2);
console.log(c / 2);
console.log("The number is " + c);
Just beware that Number instances (objects) are objects, and that very, very little code is written explicitly to work with them properly. Most code using numbers expects number primitives.
Alternatively, you could make an accessor property on Number.prototype (Pointy shows you how) that determines if the number it's called on is a multiple of PI and returns the right flag. That would give you the syntax you showed, but on all numbers. But it is a function call, so accessing the property works it out each time. Just having a isMultipleOfPI(num) function might be clearer.
In a comment you've written:
Because Number.prototype = function(){ return self % Math.PI ~ 0 } is not what I'm looking for. I would wish to distinguish between 3.14 vs 3.14 with isMultipleOfPi property.
The only way to do that is to use Number objects rather than number primitives, as described above.
You cannot add properties to specific number values; they are not objects and thus they can't have any properties. You can add properties to the Number prototype, as follows:
Object.defineProperty(Number.prototype, "isMultipleOfPi", {
get: function() {
return this.valueOf() % Math.PI === 0;
}
});
const pix2 = Math.PI * 2;
console.log(pix2.isMultipleOfPi);
console.log((7).isMultipleOfPi);
That adds a Number prototype property defined with a "get" function so that the code you posted will work as you expect. The method will be available for all numbers in your program, which doesn't seem like a bad thing if you want that feature at all.
Note also that extending built-in prototype objects is frowned upon by many people. In my example, I extended the prototype in a way that ameliorates some of the problems with extended prototypes.

SyntaxError when extending Number object

I am trying to extend the Number object with this code:
Number.prototype.isNumber = function(i){
if(arguments.length === 1){
return !isNaN(parseFloat(i)) && isFinite(i);
} else {
return !isNaN(parseFloat(this)) && isFinite(this);
}
}
try {
var x = 8.isNumber();
} catch(err) {
console.log(err);
}
I get SyntaxError: identifier starts immediately after numeric literal
also when I try the following:
Number.isNumber(8)
I get Number.isNumber is not a function!!
The JavaScript parser reads 8.isNumber as a number literal.
To access a Number method on a numeric literal you'll have to surround the number with parenthesis so the JavaScript interpreter knows you're trying to use the number properties.
Number.prototype.isNumber = function(i) {
if (arguments.length === 1) {
return !isNaN(parseFloat(i)) && isFinite(i);
}
return !isNaN(parseFloat(this)) && isFinite(this);
}
try {
var x = (8).isNumber();
console.log(x);
} catch(err) {
console.log(err);
}
I couldn't help it but provide an additional answer although you already accepted one.
The first thing you need to know, is that there is a fundamental difference between the Number object, and the Number prototype (see here).
As it stands, you are extending the Number prototype, not the object itself! Your isNumber implementation actually has the same effect like the following:
Number.prototype.isNumber = function(){return isFinite(this)}
Why? Because in order to execute this prototype method, the parser first needs to know the type of the literal you are invoking the function on. That's why you either need to turn your number literal into an expression by wrapping it in parentheses: (8).isNumber() or by using an even weirder notation 8..isNumber() (the first . is the decimal point, the second the property accessor). At this point, the javascript engine already evaluated it as a Number and thus can execute the isNumber() method.
On the other hand, although at first glimpse your code looks like it could handle the following case correctly (since you are doing a parseFloat): "8".isNumber() will always throw an exception, because here we have a string literal, and the String prototype does not have the according method. This means, you will never be able to detect numbers that are actually string literals in the first place.
What you instead should do, is directly extend the Number object so you can actually do a proper check without having to deal with errors:
Number.isFiniteNumber = function(i){
return !Number.isNaN(i) && Number.isFinite(i);
}
Number.isFiniteNumber(8); // returns true
Number.isFiniteNumber("3.141"); // returns true
Number.isFiniteNumber(".2e-34"); // returns true
Number.isFiniteNumber(Infinity); // returns false
// just for informational purposes
typeof Infinity === "number" // is true
Bonus material:
Extending native objects is potentially dangerous.
Number.isNaN() probably does not what you think it does.

why would I return a named function (object) from a javascript function?

Maybe I'm missing something obvious ... I've just started working with JavaScript, and when looking through an article about unit testing JavaScript with Jasmine, I came across this code:
function Convert(number, fromUnit) {
var conversions = {
distance : {
meters : 1,
cm : 0.01,
feet : 0.3048,
inches : 0.0254,
yards : 0.9144
},
volume : {
litres : 1,
gallons: 3.785411784,
cups : 0.236588236
}
},
betweenUnit = false,
type, unit;
for (type in conversions) {
if (conversions[type]) {
if ( (unit = conversions[type][fromUnit]) ) {
betweenUnit = number * unit * 1000;
}
}
}
return {
to : function (toUnit) {
if (betweenUnit) {
for (type in conversions) {
if (conversions.hasOwnProperty(type)) {
if ( (unit = conversions[type][toUnit]) ) {
return fix(betweenUnit / (unit * 1000));
}
}
}
throw new Error("unrecognized to-unit");
} else {
throw new Error("unrecognized from-unit");
}
function fix (num) {
return parseFloat( num.toFixed(2) );
}
}
};
}
It puzzled me as to why/how it is used, and what's the reason for it. It appears to return an object, which is a labeled function (method really, according to JavaScript naming convention), which wouldn't be called or returned upon creation.
After pondering about this and running it in chrome dev tools, it hit me that being called Convert with a capital C, it might be used as a constructor that would be used with new (again, according to JavaScript naming convention) so I might create an object like:
var tenFeet = new Convert(10, 'feet'); and then use it as tenFeet.to('cm');.
This still makes no sense, since I wouldn't call the object (read: class) Convert, since it's not converting. I'd call the to method convertTo, and probably name Convert to Measurement or something.
Is this simply bad code with bad naming, am I simply rooted too deeply in conventional OO and "formal" languages, or am I missing something basic?
When / where / why would I use something like the above: "return labeled method" from an object in JavaScript?
Couldn't the same be achieved by enhancing the prototype of Convert with the same method?
Cheers, and thanks in advance.
This is following the "read like a sentence" paradigm that some people like:
Convert(10, 'meters').to('feet') === 32.81
// Convert 10 meters to feet
You're right, the function goes against common naming conventions, but you can sort of guess that it shouldn't be created with the new keyword because there are no references to this in the function body.
This problem could've been avoided with proper documentation.
Blender answered this correctly, but just in case other people stumble upon page, here's a little more info on what's happening.
Coming from more "formal" languages, I guess I was having issues with the "label" appearance of the to in the return statement.
from MDN on Label:
Summary
Provides a statement with an identifier that you can refer to using a break or continue statement.
For example, you can use a label to identify a loop, and then use the break or continue statements to indicate whether a program should interrupt the loop or continue its execution.
Syntax
label : statement
Do notice that if you're creating an object, the syntax is similar. For example:
person={firstname:"John",lastname:"Doe",age:50,eyecolor:"blue"};
This will result in an object looking like:
object {firstname: "John", lastname: "Doe", age: 50, eyecolor: "blue"}
Another note is that if you're creating an array, you'll just use the commas, like this:
person=["John","Doe",50,"blue"];
This will give an array looking like:
["John", "Doe", 50, "blue"]
It takes a bit of time to get used to JavaScript syntax and logic, but all that really happens in my example is that the function returns an object, that has a method (named to) defined on it.
Once you have that object, you can call the method on it using the usual dot notation, which results in the chaining that is used in the above case. Or reusing Blender's example:
Convert(10, 'meters').to('feet') === 32.81`

Javascript OOP - Best practices when validating objects via interface or prototype

I am learning more advanced OO tactics for javascript coming from a C# background and am wondering about how to or if its even a good idea to implement prototype based validation. For instance when an object or function requires one of its parameters to satisfy a certain interface, you could check its interface like so,
var Interface = function Interface(i) {
var satisfied = function (t, i) {
for (var key in i) {
if (typeof t !== 'object') {
return false;
}
if (!(key in t && typeof t[key] == i[key])) {
return false;
}
}
return true;
}
this.satisfiedBy = function (t) { return satisfied(t, i); }
}
// the interface
var interfacePoint2D = new Interface({
x: 'number',
y: 'number'
});
// see if it satisfies
var satisfied = interfacePoint2D.satisfiedBy(someObject);
I came up with this strategy to validate an object by its interface only, ignoring the internal implementation of the object.
Alternatively say you are using prototype-based inheritance, should you or should not validate parameters based on their prototype functions? I understand that you'd use a prototype to implement default functionality whereas an interface doesn't specify any default functionality. Sometimes the object you are passing into a function might need certain default functionality in order for that function to work. Is it better to only validate against an interface, or should you ever validate against a prototype, and if so, whats the best way to do it?
EDIT -- I am providing some more context as to why I am asking this,
Say for instance in online game design (games written mostly in javascript). There are 2 main reasons I am interested in validation within this context,
1) Providing a strong public API for modding the game if desired
2) Preventing (or atleast discouraging greatly) potential cheaters
Which requires a balance between customizability and abuse. Specifically one situation would be in designing physics engine where objects in the game react to gravity. In a realistic system, users shouldn't be able to add objects to the system that do not react to gravity. The system has a function that expresses the global effect of gravity at any given point:
function getGravityAt(x, y) {
// return acceleration due to gravity at this point
}
And objects which react have a method that uses this to update their acceleration:
function update() {
this.acceleration = getGravity(this.position);
}
The minimum thing to do might be to ensure that any object added to the system has an 'update' method, but you still aren't ensuring that the update() method really is intended to react to gravity. If only objects that inherit from a prototypical update() method are allowed, then you know at least to some degree everything in the system reacts realistically.
This is a pretty subjective question. I'll pass on the question of whether it's a good idea to do interface-based validation in Javascript at all (there may well be good use-cases for it, but it's not a standard approach in the language). But I will say that it's probably not a good idea to validate objects based on their prototypes.
If you're validating by interface at all, you're probably working with objects created by other programmers. There are lots of ways to create objects - some rely on prototypes, some do not, and while they each have their proponents, they're all valid and likely approaches. For example:
var Point = function(x,y) {
return {
x: function() { return x },
y: function() { return y }
};
};
var p = new Point(1,1);
The object p conforms to an interface similar to yours above, except that x and y are functions. But there's no way to validate that p satisfies this interface by inspecting its constructor (which is Object()) or Point.prototype. All you can do is test that p has attributes called x and y and that they are of type "function" - what you're doing above.
You could potentially insist that p has a specific ancestor in its prototype chain, e.g. AbstractPoint, which would include the x and y functions - you can use instanceof to check this. But you can't be sure that x and y haven't been redefined in p:
var AbstractPoint = function() {};
AbstractPoint.prototype.x = function() {};
AbstractPoint.prototype.y = function() {};
var Point = function(x,y) {
var p = new AbstractPoint(x,y);
p.x = "foo";
return p;
}
var p = new Point(1,1);
p instanceof AbstractPoint; // true
p.x; // "foo"
And perhaps more importantly, this makes it harder to drop in custom objects that also satisfy the interface but don't inherit from your classes.
So I think what you're currently doing is probably the best you can hope for. In my experience, Javascript programmers are much more likely to use on-the-fly duck-typing than to try to mimic the capabilities of statically typed languages:
function doSomethingWithUntrustedPoint(point) {
if (!(point.x && point.y)) return false; // evasive action!
// etc.
}
I'll reiterate, type checking is not idiomatic javascript.
If you still want type checking, Google's closure compiler is the implementation I recommend. Type checking is done statically :) It has conventions for interfaces as well as (proto)type checking.

Override default behavior of comparison operators in JavaScript

I have a custom Javascript class (created using John Resig's Simple Javascript Inheritance). I want to be able to compare two instances of this class, using the ==, <, >, >=, and <= symbols.
How do I override the comparators of my custom class?
Try overriding valueOf(). Then you can write stuff like this:
if (obj1.valueOf() === obj2.valueOf())
if (obj1.valueOf() < obj2.valueOf())
if (obj1.valueOf() > obj2.valueOf())
So whenever I need a special JavaScript object type to override the comparison I just add valueOf to the prototype. It works great for primitive types as well since valueOf just returns the value.
Just watch out for nulls.
Lee is correct, if you implement valueOf then when comparing objects (not with === or !===) this will be used but you'll have to use toString as well because it's used when sorting arrays for some reason.
function Test(value){
this.value=value;
}
Test.prototype.toString=function(){
console.log("tostring called");
// could do something with case sensitiveness here
return new String(this.valueOf());
}
Test.prototype.valueOf=function(){
console.log("valueof called");
return this.value;
}
var t1=new Test(11);
var t2=new Test(1.1);
var arr=[t1,t2];
console.log('sorted',arr.sort().map(o=>o.value));
console.log('larger',t1>=t2);
this cannot be done in the way that you are implying it should be done (though that would be sweet). The best way I have seen this done is to implement on the prototype a set of methods to act like comparatives:
gte : function( obj ){ // greater than or equal
// return custom comparison with this as the object comparable on the left
},
gt : function( obj ){...}, // greater than but not equal
eq : function( obj ){...}, // equal to
// etc.
I was thinking about this problem somemore at work today and there is an alternate way to take advantage of the standard comparison operators but have custom object comparisons. The trick would be to have a property (getter) on the object that represented the comparable state. This would require that all instances of the object evaluate to the same numeric value given the same comparable properties. As an example let's talk vectors:
function Vector(x,y,z){
this.comp = function(){
// assuming these are floats you may wish to create a comparable level of
// precision. But this gets the point across.
return x + (y * 10) + (z * 100);
}
}
then when you set up vectors:
var v1 = new Vector(1,1,1);
var v2 = new Vector(1,0,1);
v1.comp() > v2.comp() // true
This only works of course if you are dealing with objects that can be broken down into simple numeric expression of value, but the upside is that the implementation code to get the basic effect is pretty low and you could even go so far as to make the object itself a function that returns the numeric expression of it's component parts.
function Vector(x,y,z){
var v = function v(){
return v.x + (v.y * 10) + (v.z * 100);
}
v.x = x;
v.y = y;
v.z = z;
return v;
}
now you have all the benefits of the object with easy numeric comparisons and it's even kinda terse.

Categories