[JS] JavaScript Discussion Thread

KnightNiwrem

Senior Member
Joined
Jun 1, 2014
Messages
1,057
Reaction score
0
Another epic pair of posts. You and David are like human man pages :s13:

I've never seen that sort of shim/polyfill used before, probably due to my inexperience. An interesting solution I'll definitely be messing around with for a bit.

Extending the native Function object has only 1 purpose here - that is to make Class Inheritance more intuitive when writing code. It is not required at all. If you take a look at the extending method's code, it is simply a one-liner.

The issue with Inheritance in Javascript, for some, is the flexibility of the Object.create method, coupled with the fact that all functions are actually objects, instances are objects, constructor.prototype are objects too. It just makes things all too confusing.

The above implementation attempts to make things intuitive again, by clearly defining constructors, and using the intuitive idea that only classes(which are also constructors, in this case) should extend classes.

That being said, I decided to use Object.create precisely to get around 'pretending' that JS has classes at all. I am trying to shift the mental model in my brain toward thinking about JS objects as a set of horizontally-related bundles of functionality and data, linked with [[prototype]] instead of vertical, parent-child inheritance like in Java and many other OO languages (I can read Java fine, but I can't programme with it very well).

So instead of instanceOf, which confuses me, I just used isPrototypeOf, since that will immediately tell me whether or not any particular object at run time has the functionality that it should in the prototype chain, ignoring altogether where or not it exists directly on the object itself on its .prototype property.

If I do need to extend an object, then I can always just add any functions I need directly onto the object, just declaring something like

Code:
 TestObject.prototype.getter = function () { return this.key; }

And then, if I need to use this new function in another object, I just delegate to TestObject by doing something like

Code:
var newObject = Object.create(TestObject);

So that newObject's [[Prototype]] will contain functionality from TestObject and the other objects TestObject is delegating to through its own [[Prototype]]. Now I could well be wrong, so again, please rip my little hypothesis to shreds.

First, using isPrototypeOf to replace instanceof is perfectly fine - at least, in my humble opinion. In most cases, isPrototypeOf is more general than instanceof.

I'm not entirely sure how you are doing a horizontal hierachy thing for objects and stuff here... If you are extending, it kind of looks like it would fit in a vertical hierachy just fine.

That aside, if you want to think of Objects as a bundle of functionality and data, you could look at the idea of Object Composition. Object Composition usually complements Inheritance, but it works independently from Inheritance.

Object composition attempts to describe a "has a" relationship, rather than a "is a" relationship that Inheritance does. We make this work by extracting and factorizing shared functionalities.

Constructors and classes are entirely unnecessary for Object composition because strict Object type checking doesn't seem very fruitful - the main advantage is programming speed.

Anyway, let us demonstrate some Object composition without the use of classes/constructors. For this example, I'll use Object literals and Object.create only.

Suppose I want to create a cat and a bird. Both the cat and bird can move, but only the bird can fly. Normally, we'd say that cat and bird are subclass of Animal, and then we'd override the move method for cat and bird, and extend a fly method for bird.

For Object composition, instead, we will have no "animal" class. Cat and bird are unrelated. However, cat and bird will "delegate" the move functionality to a moveComponent, while a bird will "delegate" the fly functionality to a flyComponent. A cat will not have a flyComponent.

Code:
var moveComponent = { isMoving : false,
                                   move : function() {
                                                          this.isMoving = true;
                                                       },
                                   stop : function() {
                                                          this.isMoving = false;
                                                       }
                                 };

var cat = 
{ name : "White cat",
   moveComponent : Object.create(moveComponent)
};

var flyComponent = { isFlying : false,
                              fly : function() {
                                                 this.isFlying = true;
                                 },
                              land : function() {
                                                    this.isFlying = false;
                                 }
                             };

var bird = 
{ name : "Blue bird",
   moveComponent : Object.create(moveComponent),
  flyComponent : Object.create(flyComponent)
};

Now, we tell ourselves that if we would like to check if an object is moving, we will always use the object's moveComponent - because it needs a moveComponent to be moving.

Code:
cat.moveComponent.isMoving; // false
cat.moveComponent.move();
cat.moveComponent.isMoving; // true

bird.moveComponent.isMoving; // false

cat.moveComponent.stop();
cat.moveComponent.isMoving; // false

cat.flyComponent; // undefined
cat.flyComponent.fly(); // throws error

bird.flyComponent.isFlying; // false

Note that every object has its own moveComponent object that describes the states that are related to moving, and functionality that are related to moving. Hence, they maintain some sort of independence of state between 2 different objects, while sharing functionalities.

The usefulness of this, over Inheritance, is that moveComponent and flyComponent can be applied to anything that moves or flies. Previously, if we extended bird and cat from Animal, then a car that moves too, would have to copy and paste code from Animal, or it might even extend Animal for its functionality - which hardly makes any sense.

Suppose we want to create a plane. A plane has no name, unlike animals, so extending animal would have caused problems, if we used Inheritance. Instead, a plane has a pilot.

Code:
var plane = 
{ pilot: "Natnai",
   moveComponent: Object.create(moveComponent),
   flyComponent: Object.create(flyComponent)
};

And we are done. Now, our plane has no name parameter. It has a pilot parameter. And it can move and fly without having any relationship with bird or cat.

In summary, the main advantage of Object composition is the ability to borrow functionality and reuse code without keeping track of messy hierachy and relationship between objects.
 

natnai

Supremacy Member
Joined
Nov 6, 2007
Messages
8,020
Reaction score
1
Compile, Post-link, Pre-link in Angular

Decided to post this here because I found the article really useful in helping me get to grips with the finer points of writing custom directives. A lot of books just tell you to use the link function, which works just fine MOST of the time, but clearly use compile, post-link and pre-link gives truly granular control.

I personally didn't know (stupid me) that transclude: true results in reversal of the order that Angular traverses the directive element and its children. Hope this helps someone.
 

natnai

Supremacy Member
Joined
Nov 6, 2007
Messages
8,020
Reaction score
1
Thought I would post this mini series on functional programming in JS for those who are interested in JS in the functional paradigm. If you already know the basics it'll be boring, but I'll hazard a guess that most people use JS in a non-functional way.

tech.pro/tutorial/1953/functional-javascript-part-1-introduction

Sent from Xiaomi MI PAD using GAGT
 

KnightNiwrem

Senior Member
Joined
Jun 1, 2014
Messages
1,057
Reaction score
0
Thought I would post this mini series on functional programming in JS for those who are interested in JS in the functional paradigm. If you already know the basics it'll be boring, but I'll hazard a guess that most people use JS in a non-functional way.

tech.pro/tutorial/1953/functional-javascript-part-1-introduction

Sent from Xiaomi MI PAD using GAGT

It's not a bad read, but like you said, tail-call recursion is coming soon.

As for function side-effects and mutable variables, you can impose that on yourself without an interpreter's help, as he admits.

For example, when you first asked about it, using variable declaration with 'var' instead of assignment, generally protects you from function side-effects if you use it all the time. You'd need to be familiar with scoping, of course.

As far as I see it, JS doesn't spoonfeed you useful functional functions, but you can grab them from someone's library or make your own. that aside, JS can probably do all 6 functional features the author requires, now.
 

natnai

Supremacy Member
Joined
Nov 6, 2007
Messages
8,020
Reaction score
1
It's not a bad read, but like you said, tail-call recursion is coming soon.

As for function side-effects and mutable variables, you can impose that on yourself without an interpreter's help, as he admits.

For example, when you first asked about it, using variable declaration with 'var' instead of assignment, generally protects you from function side-effects if you use it all the time. You'd need to be familiar with scoping, of course.

As far as I see it, JS doesn't spoonfeed you useful functional functions, but you can grab them from someone's library or make your own. that aside, JS can probably do all 6 functional features the author requires, now.
Combined with generators in ES6 and Symbol.itetator,TCO is going to be big for functional JS. I really like where JS is headed now and I've completely switched to a full JS stack.

Like you say you can just use lodash or underscore for functional helpers. Easy curries anyone? :D

Oh also, if you're not disciplined and want to go full functional, ClojureScript seems a good alternative, although I've not had the time to mess around with it.

Sent from Xiaomi MI 3W using GAGT
 
Last edited:
Important Forum Advisory Note
This forum is moderated by volunteer moderators who will react only to members' feedback on posts. Moderators are not employees or representatives of HWZ Forums. Forum members and moderators are responsible for their own posts. Please refer to our Community Guidelines and Standards and Terms and Conditions for more information.
Top