I've been doing a project at work recently focused on an almost entirely client-driven web site. Obviously Javascript is used heavily, and I've been using jQuery on top of it which has turned out to be an absolute pleasure to work with.
One of the things that has surprised me in this is how much I like the JSON object syntax and it's use within javascript (highlighted by jQuery, which uses it everywhere). for those that aren't familiar with it, consider this brief example:
function add(params) {
params.result(params.a, params.b);
}
add({
a: 1,
b: 2,
result: function(value) {
alert(value);
}
});
Of course, this example is extremely contrived but it illustrates the basic usage. The JSON describes an object on the fly, passed in this case as a parameter to the function, and even defines a function within it for use as a callback. I personally find this methodology very easy to use, understand, and produce APIs with (though I know there are those that would disagree with me.)
So my question is, is this type of syntax unique to javascript? I know that many languages have JSON parsers (and have used several) but they don't allow for this sort of inlined declaration. And granted, much of what you can do with this syntax can be duplicated via named parameters in various languages and lambda expressions or function pointers (Python jumps to mind), but I still don't find that quite as elegant.
Just curious, thanks for any replies!
The canonical example is Lisp: in Lisp, the language isn't even defined in terms of text, it is defined in terms of data structures. There really is not difference between code and data: code is just a list whose first element is interpreted as an operation and the rest as operands.
Writing a program is just writing lists.
Lua uses "tables" which are pretty much identical to javascript objects.
Syntax of JSON is very similar to Perl definition of complex structures. And your example would be:
#!/usr/bin/perl
use strict;
use warnings;
use signatures;
sub add($hash) {
$hash->{result}($hash->{a}, $hash->{b});
}
add({
a=> 1,
b=> 2,
result=> sub ($val) {
print "$val\n";
}
});
C# 3.0 has something similar in that you can both instantiate an object using a default constructor and assign properties in the same statement. It's really just a bit of syntactic sugar, but it really make it much easier than declaring multiple constructors just to handle various combinations of parameter settings. It looks like:
var myObject = new MyClass { Property1 = "value", NumericProperty = 1 };
There are also anonymous types in C# 3.0 which have a similar syntax; these are frequently used with LINQ
var query = dataContext.Entity
.Where( e => e.Kind = 1 )
.Select( e => new { e.Name, e.Kind } );
This results in an IEnumerable of a new anonymous type with properties "Name" and "Kind" which, in turn, have the same types as the corresponding entity properties.
Rubists would do:
def add(params) {
params.result(params.a, params.b)
}
add({:a=> 1, :b=> 2}) do |value|
alert(value)
end
The passing of an optional block is kind of a weird idiom in ruby. Or to be more true to your example.
def add(params) {
params.result(params.a, params.b)
}
add({
:a=> 1,
:b=> 2,
:result=> proc do |value|
alert(value)
end
})
But the concept of the inline function originates from lambda calculus and LISP.
Related
In javascript I know i can something like the following:
var foo = '';
function changeVariable(variable, data){
this[variable] = data;
}
changeVariable("foo", "bar");
Is there away I can do this in swift?
func toggleFadeIn (element: String, active: Bool)
{
if(!active){
self.element.alpha = 0;
self.element.transform = CGAffineTransform(translationX: 0, y: 25)
}
}
Javascript is a dynamic language that has the facilities of modifying objects in such a way at runtime.
Static languages (like Swift, Java, C#, and many others) require a reflection library to implement such behaviour. Unfortunately, Swift has a really limited reflection capability (Mirror) and doesn't have the ability to modify object/struct members by their String names, yet.
If you elaborate on what exactly you were trying to achieve with this, we would be better able to suggest solutions.
What you describe IS possible using KVO on NSObjects. It relies on Objective-C dynamic messaging, but it does work. Take a look a the function setValue:forKey:, as documented in Apple's Key Value Programming Guide.
Note that this is decidedly un-swiftlike, and not recommended.
In Douglas Crockford's book "Javascript: The Good Parts" he provides code for a curry method which takes a function and arguments and returns that function with the arguments already added (apparently, this is not really what "curry" means, but is an example of "partial application"). Here's the code, which I have modified so that it works without some other custom code he made:
Function.prototype.curry = function(){
var slice = Array.prototype.slice,
args = slice.apply(arguments),
that = this;
return function() {
// context set to null, which will cause `this` to refer to the window
return that.apply(null, args.concat(slice.apply(arguments)));
};
};
So if you have an add function:
var add = function(num1, num2) {
return num1 + num2;
};
add(2, 4); // returns 6
You can make a new function that already has one argument:
var add1 = add.curry(1);
add1(2); // returns 3
That works fine. But what I want to know is why does he set this to null? Wouldn't the expected behavior be that the curried method is the same as the original, including the same this?
My version of curry would look like this:
Function.prototype.myCurry = function(){
var slice = [].slice,
args = slice.apply(arguments),
that = this;
return function() {
// context set to whatever `this` is when myCurry is called
return that.apply(this, args.concat(slice.apply(arguments)));
};
};
Example
(Here is a jsfiddle of the example)
var calculator = {
history: [],
multiply: function(num1, num2){
this.history = this.history.concat([num1 + " * " + num2]);
return num1 * num2;
},
back: function(){
return this.history.pop();
}
};
var myCalc = Object.create(calculator);
myCalc.multiply(2, 3); // returns 6
myCalc.back(); // returns "2 * 3"
If I try to do it Douglas Crockford's way:
myCalc.multiplyPi = myCalc.multiply.curry(Math.PI);
myCalc.multiplyPi(1); // TypeError: Cannot call method 'concat' of undefined
If I do it my way:
myCalc.multiplyPi = myCalc.multiply.myCurry(Math.PI);
myCalc.multiplyPi(1); // returns 3.141592653589793
myCalc.back(); // returns "3.141592653589793 * 1"
However, I feel like if Douglas Crockford did it his way, he probably has a good reason. What am I missing?
Reader beware, you're in for a scare.
There's a lot to talk about when it comes to currying, functions, partial application and object-orientation in JavaScript. I'll try to keep this answer as short as possible but there's a lot to discuss. Hence I have structured my article into several sections and at the end of each I have summarized each section for those of you who are too impatient to read it all.
1. To curry or not to curry
Let's talk about Haskell. In Haskell every function is curried by default. For example we could create an add function in Haskell as follows:
add :: Int -> Int -> Int
add a b = a + b
Notice the type signature Int -> Int -> Int? It means that add takes an Int and returns a function of type Int -> Int which in turn takes an Int and returns an Int. This allows you to partially apply functions in Haskell easily:
add2 :: Int -> Int
add2 = add 2
The same function in JavaScript would look ugly:
function add(a) {
return function (b) {
return a + b;
};
}
var add2 = add(2);
The problem here is that functions in JavaScript are not curried by default. You need to manually curry them and that's a pain. Hence we use partial application (aka bind) instead.
Lesson 1: Currying is used to make it easier to partially apply functions. However it's only effective in languages in which functions are curried by default (e.g. Haskell). If you have to manually curry functions then it's better to use partial application instead.
2. The structure of a function
Uncurried functions also exist in Haskell. They look like functions in "normal" programming languages:
main = print $ add(2, 3)
add :: (Int, Int) -> Int
add(a, b) = a + b
You can convert a function in its curried form to its uncurried form and vice versa using the uncurry and curry functions in Haskell respectively. An uncurried function in Haskell still takes only one argument. However that argument is a product of multiple values (i.e. a product type).
In the same vein functions in JavaScript also take only a single argument (it just doesn't know it yet). That argument is a product type. The arguments value inside a function is a manifestation of that product type. This is exemplified by the apply method in JavaScript which takes a product type and applies a function to it. For example:
print(add.apply(null, [2, 3]));
Can you see the similarity between the above line in JavaScript and the following line in Haskell?
main = print $ add(2, 3)
Ignore the assignment to main if you don't know what it's for. It's irrelevant apropos to the topic at hand. The important thing is that the tuple (2, 3) in Haskell is isomorphic to the array [2, 3] in JavaScript. What do we learn from this?
The apply function in JavaScript is the same as function application (or $) in Haskell:
($) :: (a -> b) -> a -> b
f $ a = f a
We take a function of type a -> b and apply it to a value of type a to get a value of type b. However since all functions in JavaScript are uncurried by default the apply function always takes a product type (i.e. an array) as its second argument. That is to say that the value of type a is actually a product type in JavaScript.
Lesson 2: All functions in JavaScript only take a single argument which is a product type (i.e. the arguments value). Whether this was intended or happenstance is a matter of speculation. However the important point is that you understand that mathematically every function only takes a single argument.
Mathematically a function is defined as a morphism: a -> b. It takes a value of type a and returns a value of type b. A morphism can only have one argument. If you want multiple arguments then you could either:
Return another morphism (i.e. b is another morphism). This is currying. Haskell does this.
Define a to be a product of multiple types (i.e. a is a product type). JavaScript does this.
Out of the two I prefer curried functions as they make partial application trivial. Partial application of "uncurried" functions is more complicated. Not difficult, mind you, but just more complicated. This is one of the reasons why I like Haskell more than JavaScript: functions are curried by default.
3. Why OOP matters not
Let's take a look at some object-oriented code in JavaScript. For example:
var oddities = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].filter(odd).length;
function odd(n) {
return n % 2 !== 0;
}
Now you might wonder how is this object-oriented. It looks more like functional code. After all you could do the same thing in Haskell:
oddities = length . filter odd $ [0..9]
Nevertheless the above code is object-oriented. The array literal is an object which has a method filter which returns a new array object. Then we simply access the length of the new array object.
What do we learn from this? Chaining operations in object-oriented languages is the same as composing functions in functional languages. The only difference is that the functional code reads backwards. Let's see why.
In JavaScript the this parameter is special. It's separate from the formal parameters of the function which is why you need to specify a value for it separately in the apply method. Because this comes before the formal parameters, methods are chained from left-to-right.
add.apply(null, [2, 3]); // this comes before the formal parameters
If this were to come after the formal parameters the above code would probably read as:
var oddities = length.filter(odd).[0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
apply([2, 3], null).add; // this comes after the formal parameters
Not very nice is it? Then why do functions in Haskell read backwards? The answer is currying. You see functions in Haskell also have a "this" parameter. However unlike in JavaScript the this parameter in Haskell is not special. In addition it comes at the end of the argument list. For example:
filter :: (a -> Bool) -> [a] -> [a]
The filter function takes a predicate function and a this list and returns a new list with only the filtered elements. So why is the this parameter last? It makes partial application easier. For example:
filterOdd = filter odd
oddities = length . filterOdd $ [0..9]
In JavaScript you would write:
Array.prototype.filterOdd = [].filter.myCurry(odd);
var oddities = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].filterOdd().length;
Now which one would you choose? If you're still complaining about reading backwards then I have news for you. You can make Haskell code read forwards using "backward application" and "backward composition" as follows:
($>) :: a -> (a -> b) -> b
a $> f = f a
(>>>) :: (a -> b) -> (b -> c) -> (a -> c)
f >>> g = g . f
oddities = [0..9] $> filter odd >>> length
Now you have the best of both worlds. Your code reads forwards and you get all the benefits of currying.
There are a lot of problems with this that don't occur in functional languages:
The this parameter is specialized. Unlike other parameters you can't simply set it to an arbitrary object. Hence you need to use call to specify a different value for this.
If you want to partially apply functions in JavaScript then you need to specify null as the first parameter of bind. Similarly for call and apply.
Object-oriented programming has nothing to do with this. In fact you can write object-oriented code in Haskell as well. I would go as far as to say that Haskell is in fact an object-oriented programming language, and a far better one at that than Java or C++.
Lesson 3: Functional programming languages are more object-oriented than most mainstream object-oriented programming languages. In fact object-oriented code in JavaScript would be better (although admittedly less readable) if written in a functional style.
The problem with object-oriented code in JavaScript is the this parameter. In my humble opinion the this parameter shouldn't be treated any differently than formal parameters (Lua got this right). The problem with this is that:
There's no way to set this like other formal parameters. You have to use call instead.
You have to set this to null in bind if you wish to only partially apply a function.
On a side note I just realized that every section of this article is becoming longer than the preceding section. Hence I promise to keep the next (and final) section as short as possible.
4. In defense of Douglas Crockford
By now you must have picked up that I think that most of JavaScript is broken and that you should shift to Haskell instead. I like to believe that Douglas Crockford is a functional programmer too and that he is trying to fix JavaScript.
How do I know that he's a functional programmer? He's the guy that:
Popularized the functional equivalent of the new keyword (a.k.a Object.create). If you don't already do then you should stop using the new keyword.
Attempted to explain the concept of monads and gonads to the JavaScript community.
Anyway, I think Crockford nullified this in the curry function because he knows how bad this is. It would be sacrilege to set it to anything other than null in a book entitled "JavaScript: The Good Parts". I think he's making the world a better place one feature at a time.
By nullifying this Crockford is forcing you to stop relying on it.
Edit: As Bergi requested I'll describe a more functional way to write your object-oriented Calculator code. We will use Crockford's curry method. Let's start with the multiply and back functions:
function multiply(a, b, history) {
return [a * b, [a + " * " + b].concat(history)];
}
function back(history) {
return [history[0], history.slice(1)];
}
As you can see the multiply and back functions don't belong to any object. Hence you can use them on any array. In particular your Calculator class is just a wrapper for list of strings. Hence you don't even need to create a different data type for it. Hence:
var myCalc = [];
Now you can use Crockford's curry method for partial application:
var multiplyPi = multiply.curry(Math.PI);
Next we'll create a test function to multiplyPi by one and to go back to the previous state:
var test = bindState(multiplyPi.curry(1), function (prod) {
alert(prod);
return back;
});
If you don't like the syntax then you could switch to LiveScript:
test = do
prod <- bindState multiplyPi.curry 1
alert prod
back
The bindState function is the bind function of the state monad. It's defined as follows:
function bindState(g, f) {
return function (s) {
var a = g(s);
return f(a[0])(a[1]);
};
}
So let's put it to the test:
alert(test(myCalc)[0]);
See the demo here: http://jsfiddle.net/5h5R9/
BTW this entire program would have been more succinct if written in LiveScript as follows:
multiply = (a, b, history) --> [a * b, [a + " * " + b] ++ history]
back = ([top, ...history]) -> [top, history]
myCalc = []
multiplyPi = multiply Math.PI
bindState = (g, f, s) -->
[a, t] = g s
(f a) t
test = do
prod <- bindState multiplyPi 1
alert prod
back
alert (test myCalc .0)
See the demo of the compiled LiveScript code: http://jsfiddle.net/5h5R9/1/
So how is this code object oriented? Wikipedia defines object-oriented programming as:
Object-oriented programming (OOP) is a programming paradigm that represents concepts as "objects" that have data fields (attributes that describe the object) and associated procedures known as methods. Objects, which are usually instances of classes, are used to interact with one another to design applications and computer programs.
According to this definition functional programming languages like Haskell are object-oriented because:
In Haskell we represent concepts as algebraic data types which are essentially "objects on steroids". An ADT has one or more constructors which may have zero or more data fields.
ADTs in Haskell have associated functions. However unlike in mainstream object-oriented programming languages ADTs don't own the functions. Instead the functions specialize upon the ADTs. This is actually a good thing as ADTs are open to adding more methods. In traditional OOP languages like Java and C++ they are closed.
ADTs can be made instances of typeclasses which are similar to interfaces in Java. Hence you still do have inheritance, variance and subtype polymorphism but in a much less intrusive form. For example Functor is a superclass of Applicative.
The above code is also object-oriented. The object in this case is myCalc which is simply an array. It has two functions associated with it: multiply and back. However it doesn't own these functions. As you can see the "functional" object-oriented code has the following advantages:
Objects don't own methods. Hence it's easy to associate new functions to objects.
Partial application is made simple via currying.
It promotes generic programming.
So I hope that helped.
Reason 1 - not easy to provide a general solution
The problem is that your solution is not general. If the caller doesn't assign the new function to any object, or assigns it to a completely different object, your multiplyPi function will stop working:
var multiplyPi = myCalc.multiply.myCurry(Math.PI);
multiplyPi(1); // TypeError: this.history.concat is not a function
So, neither Crockford's nor your solution can assure that the function will be used correctly. Then it may be easier to say that the curry function works only on "functions", not "methods", and set this to null to force that. We might only speculate though, since Crockford doesn't mention that in the book.
Reason 2 - functions are being explained
If you asking "why Crockford didn't use this or that" - the very likely answer is: "It wasn't important in regard to the demonstrated matter." Crockford uses this example in the chapter Functions. The purpose of the sub-chapter curry was:
to show that functions are objects you can create and manipulate
to demonstrate another usage of closures
to show how arguments can be manipulated.
Finetuning this for a general usage with objects was not purpose of this chapter. As it is problematic if not even impossible (see Reason 1), it was more educational to put there just null instead if putting there something which could raise questions if it actually works or not (didn't help in your case though :-)).
Conclusion
That said, I think you can be perfectly confident in your solution! There's no particular reason in your case to follow Crockfords' decision to reset this to null. You must be aware though that your solution only works under certain circumstances, and is not 100% clean. Then clean "object oriented" solution would be to ask the object to create a clone of its method inside itself, to ensure that the resultant method will stay within the same object.
But what I want to know is why does he set this to null?
There is not really a reason. Probably he wanted to simplify, and most functions that make sense to be curried or partially applied are not OOP-methods that use this. In a more functional style the history array that is appended to would be another parameter of the function (and maybe even a return value).
Wouldn't the expected behavior be that the curried method is the same as the original, including the same this?
Yes, your implementation makes much more sense, however one might not expect that a partially applied function still needs to be called in the correct context (as you do by re-assigning it to your object) if it uses one.
For those, you might have a look at the bind method of Function objects for partial application including a specific this-value.
From MDN:
thisArg The value of this provided for the call to fun. Note that this
may not be the actual value seen by the method: if the method is a
function in non-strict mode code, null and undefined will be replaced
with the global object, and primitive values will be boxed.
Hence, if the method is in non-strict mode and the first argument is null or undefined, this inside of that method will reference Window. In strict mode, this is null or undefined. I've added a live example on this Fiddle.
Furthermore passing in nullor undefined does not do any harm in case the function does not reference this at all. That's probably why Crockford used null in his example, to not overcomplicate things.
I come from a C# background. I've been working a lot with JavaScript lately. On a new app, I have a mysql/php back end. I'm going to be passing a lot of "types" back and forth.
So in my data base, I have several tables like
table1
id, fieldx,fieldy,fieldz
table2
id, fielda,fieldb,fielc
In c# I would definitely write classes for all those in the code. Which led me to implement things like so (in my JavaScript app):
function table1(id, x,y,z){
this.id=id;
this.x=x;
this.y=y;
this.z=z;
}
After about 6 tables worth of that, it suddenly occurred to me that maybe there was no point at all in making these classes.
So my question is, in a JavaScript app, do I use "classes" for data types? or should I just "document" which fields/types are expected and so in the code instead of
a.push(new table1(5,1,2,3));
I would just have
a.push({id:5,x:1,y:2,z:3});
This may seem like a preferences question but it's a fundamental language question that I have as I try to understand how to model my app's data in JavaScript. Is there any advantage of the classes (with only data fields) or is it just a mistake. Thanks.
It depends,
Note: Most of the programmers coming from a strong OO language will have trouble like you in regard to JavaScript's functional behavior (you are not alone).
If you want to create something closer to C# I would do the following:
function Table1(id, x, y, z) {
this.id=id;
this.x=x;
this.y=y;
this.z=z;
}
Table1.prototype.mySpecialTable1Method= function()
{
console.log(this.id);
};
Implementation:
var t = new Table1(1, 2, 3, 4);
t.mySpecialTable1Method();// outputs: 1
If you need to have methods that interact with the (soon to be) objects then I would definitely go with the code above. In addition it will make it clear when working with the objects that are related to a specific 'type' (naming the data).
But if your objects do not require any special "treatment" then I don't see any problem to use normal js object literals and pass them along (probably good for small projects).
Something along the lines:
var table1 = {};
table1.id = 1;
table1.x = 2;
table1.y = 3;
table1.z = 4;
console.log(table1.id); //outputs: 1
Extra reference:
http://www.youtube.com/watch?v=PMfcsYzj-9M
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript
Update:
For the sake of readability and scalability and the point that you are coming from C# you may want to stick to the "class" implementation just because it will define the correlation between the raw data and the objects you are working with.
There is a good chance that you are going to work with some data that will probably be messy and unorganized.
MVC may be the solution for you. It tries to bring some order to the chaos that you are expecting. I recommend to check out some of them like: AngularJS or Ember.
Another solution may be reactive js - but mostly if you are going to interact with the DOM according to your data (ReactJS, and Facebook's React as some good ones).
As a note for security, I would like to add that mapping the data closely to the db isn't a best practice but its your call.
Javascript is a funny language, and there are plenty of ways to do things. An Object is an Object in Javascript with or without a name. {} is just a short-hand way to create one.
If you are going for readability, then your initial example would be the way to go.
If you just want to get the block of data into an array, then your second example is appropriate. Personally, I would use your later example if it is just data.
If you are using functions and what not as well as data storage, and plan on reusing it several times in your code, then yes, define your object and call it appropriately.
JavaScript has no classes, it is a functional language and a function is a first class citizen in js meaning that a function is an object.
From your example I can see that your intention for classes is simply to pass data and using json is perfect for this.
I have a very common pattern of "given a Foo, return a Bar," for example, given a user_id, return a User.
Is there a conventional naming pattern for these sorts of functions? Following Joel on Software, I've personally used a lot of bar_from_foo(), but I rarely see other people do this and it quickly becomes verbose, e.g.
widgets = user_widgets_from_user(user_from_param_map(params))
Is there a conventional way to name, or namespace (e.g. User.from_map()) in any of the popular languages out there? I am particularly interested in Python but any language you can think of would br useful.
I would take advantage of Clojure's naming flexibility and call it:
(defn foo->bar [] ...)
To me that makes the intent quite clear and it's pretty short.
In Python, and various other OO languages, this should be a constructor on Bar that takes a single Foo as its only argument. Since Python doesn't do method overloading (and attempts to emulate it are usually fragile), if Bar.__init__ already takes a different signature, then the convention is exactly your last one. Importantly, this is usually defined as a class method rather than a static method (for the benefit of subclasses):
class Bar:
#classmethod
def from_foo(cls, f):
'''Create a new Bar from the given Foo'''
ret = cls()
# ...
If you want to convert something into another, for example a string to an integer, the method is to be defined on the receiver, and hence its class is clear, so you should not put the receiver class as part of the method name: String#to_i, not String#string_to_i. This in one of the core ideas of object oriented programming (polymorphism).
If the receiver is too general to be assigned such method, for example if user_id is a mere string, and defining a method on String to convert it to a User does not look right, then you should define a constructor method on the class that you expect the return value to be: User.new or User.from_id.
I think it depends a lot on context and choosing a meaningful metaphor. ActiveRecord for instance uses the class method "find" for finding records in the database, a more meaningful idea than "input a user_id, output a user". For example:
User.find(user_id)
User.find_by_email(user_email)
For conversions, I usually like to write the conversion methods to make it easy to use in higher order functions. For example in ruby, conversions are often done with to_* instance methods, for example to convert a Foo to a Bar it would make sense to have a to_bar method for all foos, so you could write:
foo = Foo.new(...) # make a new Foo
bar = foo.to_bar # convert it to a Bar
And then to convert a bunch of foos, you could simply:
bars = foos.map(&:to_bar)
Ruby also tends to have Foo.parse(str) for converting a string to the object.
For javascript, I like having class methods (which I got from standard ml), for example:
Foo.toBar = function(foo) {
return new Bar(...);
};
And then you can map over it as well (using underscore in this example):
var bars = _.map(foos, Foo.toBar);
the Standard ML convention is structure (class) methods. Example fn types:
Foo.toBar : foo -> bar
Foo.fromBar : bar -> foo
And you'd use it like:
val bar = Foo.toBar foo;
val bars = map Foo.toBar foos;
Why placing the type of the parameter the name of the function? I think it would be clearer something like
a_bar = bar_from(a_foo)
then you can rely on dynamic dispatch or overload in many languages... for example in Python the implementation could try to call x.toBar() if present or it could check for a global registry like Bar_builders[type(x)](x); in Lisp you could rely on methods; in C++ on overloads...
In Ruby, you can capture a call to a method which is missing and define it on the fly.
What I wanna accomplish in JavaScript is to have an object with no methods. I want a missing method to be translated into a call to emit():
app.isReady() -> app.emit("isReady")
soldier.kills() -> soldier.emit("kills")
I think it's better to capture the missing method error and run emit(methodName) rather than defining all methods (from a fixed list) at runtime. That way we don't have performance overhead if there are hundreds or thousands of events for an object.
What is the best way to do this?
UPDATE: This is an API design so I rather stay out of:
try {
app.isReady()
} catch(e) {
...
}
I want to know how I can accomplish this behind the scenes so the users can use methods as usual.
In that way we don't have a performance overhead if there are hundreds/thousands of events for an object.
I think it's a massive misconception to think the performance overhead of adding methods to an object is smaller then the performance overhead of converting method invocations into emit calls.
However you cannot implement this feature in ES5
One could however implement this using Harmony proxies.
I recommend looking at simulating __noSuchMethod__.
I believe ES6 proxies are experimental and can be turned on in V8 so you could use them with node.js today.
It's not possible to do that consistently at this stage, unless you can guarantee your app will only run on Mozilla, in which case noSuchMethod is what you're after.
As far as I know, none of the other browsers implement this yet.
Use a RegExp test on the function pointer by using the following process:
pass the object literal as an argument
pass the name of the default method as a string
pass the name of the fallback method as a string
using subscript notation to dereference the function pointer
use a regexp to check the type against the name function
if it succeeds, call the default using subscript notation
if it fails, call the fallback using subscript notation
For example:
/* Define mapping */
var app = {"emit": emit};
/* Define interface */
function emit(){}
function \u1000missing(object, method, fallback)
{
/* Existence check */
if (/function/.test(object[method]) )
{
object[method]();
}
/* reify */
else
{
object[fallback](method)
}
}
\u1000missing(app,"isReady","emit")
You might ask why you'd ever want to use subscript notation. Subscript notation allows for dynamic creation of properties and methods. So if you ever do any sort of metaprogramming, you'll most likely be using the subscript notation.
References
Are there equivalents to Ruby's method_missing in other languages?
JSPerf: Method Missing
Handling a call to a missing method in different languages
jQuery is a Monad
Message forwarding in Smalltalk
Performance from Aligning Smalltalk and JavaScript Classes
Can Perl be Smalltalk?
How learning Smalltalk can make you a better developer
Reflective Facilities in Smalltalk-80
12.1. QMetaObject - The Meta Object Pattern
Object Programming and Object-Oriented Programming
Things you should know about JavaScript
Respond to an Unknown Method Call
Creating Thread-Safe Components With OnMissingMethod()
On the design of the ECMAScript Reflection API (pdf)
Does Not Understand
I've create a Node.js package to deal with your situation. It's called auto-object.
Here's a glance:
const myObject = autoObject.createObject(function(name) {
if(name.startsWith("say")) {
return function() {
return name.substr(3);
}
}
return name;
});
myObject.foo; ///< "foo"
myObject.sayFoo(); ///< "Foo"
myObject.sayBar(); ///< "Bar"
What's more, this works with class too.