[JS] JavaScript Discussion Thread

natnai

Supremacy Member
Joined
Nov 6, 2007
Messages
8,020
Reaction score
1
Hey guys, I noticed these forums are really not very active, which is a shame. So I've decided to start this little thread for everyone who works with JavaScript in any form to share anything interesting that you come across in the course of your work/studies/whatever. Hopefully we can all help each other become better JavaScript developers :)

To kick things off, I'll just write a small snippet on Prototypes in JS. They were very confusing for me when I first started, since I began by learning C++ (very basic) and then PHP, which I really liked.

As you all know, PHP follows a classical OO architecture, like Java. Javascript doesn't. Javascript utilises Prototypal Inheritance, which due to confusing operators like
Code:
new
, I think most programmers new to JS misunderstand.

Consider the following snippet:

Code:
function Foo() {};
Foo.prototype.key = 'fooValue';

var Bar = Object.create(Foo);
Bar.prototype = Object.create(Foo.prototype);

Bar.prototype.key = 'barValue';

var BarProto = Object.getPrototypeOf(Bar);

console.log(BarProto);
console.log(Foo.prototype.key); // fooValue
console.log(Bar.prototype.key); // barValue

Now consider this one:

Code:
function Foo() {};
Foo.prototype.key = 'fooValue';

var Bar = Object.create(Foo);
Bar.prototype.key = 'barValue';

var BarProto = Object.getPrototypeOf(Bar); // Foo() {}

console.log(BarProto);
console.log(Foo.prototype.key); // barValue - wtf????
console.log(Bar.prototype.key); // barValue

The second snippet shows that Foo.prototype and Bar.prototype are actually the same object. That's because there are no classes in JavaScript whatsoever: there are only objects, and other objects are linked by reference to the prototypes of their ancestors. That's why assigning
Code:
'barValue'
to Bar.prototype.key also changed the value of Foo.prototype.key.

For me this was very frustrating, until I found out how JavaScript prototypes _actually_ works. If you want to COPY and not REFERENCE a prototype, then you should do:

Code:
Bar.prototype = Object.create(Foo.prototype);
Bar.prototype.key = 'barValue';

That results in the assignment working as expected (see the first snippet). That's because Object.create copies the Foo.prototype in its entirety and assigns it to Bar.prototype, instead of just creating a reference through the internal [[Prototype]] property of Bar.

That's all from me! I hope other members will contribute as well, so we can all learn together. Cheers!
 

Noroto

Master Member
Joined
Mar 24, 2005
Messages
3,803
Reaction score
0
It is time to learn ES6 standard instead of the old way. ES6 is relatively more "OO" like.

Although ES6 is not implemented in browser, you can transpile it to ES5 which is the present JS.
 

natnai

Supremacy Member
Joined
Nov 6, 2007
Messages
8,020
Reaction score
1
It is time to learn ES6 standard instead of the old way. ES6 is relatively more "OO" like.

Although ES6 is not implemented in browser, you can transpile it to ES5 which is the present JS.

I've been using Promises, but the new Class and Super keywords seem like syntactic sugar to me. In the current draft spec, it's clearly stated that the substance of prototypal inheritance will stay - so it's still important to understand how the prototype chain works, imo.
 

natnai

Supremacy Member
Joined
Nov 6, 2007
Messages
8,020
Reaction score
1
I don't understand. Why don't you do this instead?

Source

That's because 'new' means the 'newed' object gets executed as well when it's instantiated. Now, that's fine if the 'newed' object doesn't change the program's state in any way, but what if it does? Then it might have some unintended consequences right? That's what I think anyway - correct me if i'm wrong.

Edit:

see this fiddle for a demonstration of what I mean - http://jsfiddle.net/rbegcex5/
 
Last edited:

davidktw

Arch-Supremacy Member
Joined
Apr 15, 2010
Messages
13,547
Reaction score
1,301
That's because 'new' means the 'newed' object gets executed as well when it's instantiated. Now, that's fine if the 'newed' object doesn't change the program's state in any way, but what if it does? Then it might have some unintended consequences right? That's what I think anyway - correct me if i'm wrong.

Edit:

see this fiddle for a demonstration of what I mean - http://jsfiddle.net/rbegcex5/

The "new" operator in Javascript seems to be doing pretty much the same as what is happening for the Class OO model. Except Javascript has too much legacy with its prototype OO model that makes the whole experience messy.

Classes in Java are largely immutable unless you touch on AOP which is not the case for Javascript in this context.

http://raganwald.com/2014/01/14/the-new-javascript-problem.html

However in my experiences with OO, I generally find the reasoning and intuition of Class OO model more consistent and earlier to logically reason
 

KnightNiwrem

Senior Member
Joined
Jun 1, 2014
Messages
1,057
Reaction score
0
That's because 'new' means the 'newed' object gets executed as well when it's instantiated. Now, that's fine if the 'newed' object doesn't change the program's state in any way, but what if it does? Then it might have some unintended consequences right? That's what I think anyway - correct me if i'm wrong.

Edit:

see this fiddle for a demonstration of what I mean - http://jsfiddle.net/rbegcex5/

Now I'm even more confused.

If it does create the side-effect you mentioned, why would you not define function MorphingTime's body as "this.bar = 'foobar';"?

Note that your implementation in your first post introduces more problems - Inheritance is broken, for example. Instanceof no longer works because javascript does not see your new object as a instance of the object.

On the other hand, you get something weird like (Bar.prototype instanceof Foo === true). So now, Bar's prototype is an instance of Foo, but Bar, itself, isn't.

Furthermore, your object has a prototype object - which is weird for an instance. Note that if you try to implement the code in your original post using 'new', the new instance "loses" the prototype object.
 
Last edited:

natnai

Supremacy Member
Joined
Nov 6, 2007
Messages
8,020
Reaction score
1
Now I'm even more confused.

If it does create the side-effect you mentioned, why would you not define function MorphingTime's body as "this.bar = 'foobar';"?

Note that your implementation in your first post introduces more problems - Inheritance is broken, for example. Instanceof no longer works because javascript does not see your new object as a instance of the object.

On the other hand, you get something weird like (Bar.prototype instanceof Foo === true). So now, Bar's prototype is an instance of Foo, but Bar, itself, isn't.

Furthermore, your object has a prototype object - which is weird for an instance. Note that if you try to implement the code in your original post using 'new', the new instance "loses" the prototype object.

I just did that to demonstrate how 'new' doesn't instantiate an object like new would in say, Java or PHP - coz you can't execute a class in classical OO languages. But in JS, when you use new, you call the constructor function too, and if it happens to change state on some other variable that isn't in its scope, then that leads to unexpected consequences.

So that's why all along I always used Object.create. As for the other stuff, I'm going to set up a couple of experimental fiddles and report back...but just off the top of my head, why would instanceOf not work? var Bar = Object.create(Foo) followed by Bar.prototype = Object.create(Foo.prototype)...would Bar instanceOf Foo not return true? And then Bar.prototype instanceOf Foo.prototype == true
 

natnai

Supremacy Member
Joined
Nov 6, 2007
Messages
8,020
Reaction score
1
The "new" operator in Javascript seems to be doing pretty much the same as what is happening for the Class OO model. Except Javascript has too much legacy with its prototype OO model that makes the whole experience messy.

Classes in Java are largely immutable unless you touch on AOP which is not the case for Javascript in this context.

http://raganwald.com/2014/01/14/the-new-javascript-problem.html

However in my experiences with OO, I generally find the reasoning and intuition of Class OO model more consistent and earlier to logically reason

Really had a hard time with OO JS until recently tbh, then I forced myself to get to grips with it because I realised I had to start rolling my own modules/plugins coz the plug and play ones didn't give me all the flexibility I needed/wanted.

I still have to work out quite a few of the nuances involved with prototypal inheritance...which is really the purpose of starting this thread :s13:
 

KnightNiwrem

Senior Member
Joined
Jun 1, 2014
Messages
1,057
Reaction score
0
I just did that to demonstrate how 'new' doesn't instantiate an object like new would in say, Java or PHP - coz you can't execute a class in classical OO languages. But in JS, when you use new, you call the constructor function too, and if it happens to change state on some other variable that isn't in its scope, then that leads to unexpected consequences.

So that's why all along I always used Object.create. As for the other stuff, I'm going to set up a couple of experimental fiddles and report back...but just off the top of my head, why would instanceOf not work? var Bar = Object.create(Foo) followed by Bar.prototype = Object.create(Foo.prototype)...would Bar instanceOf Foo not return true? And then Bar.prototype instanceOf Foo.prototype == true

Code:
// ------------------------------------------------------

function Foo() {};
Foo.prototype.key = 'fooValue';

var Bar = Object.create(Foo);
Bar.prototype = Object.create(Foo.prototype);

// ------------------------------------------------------

Bar instanceof Foo; // false

Bar.prototype instanceof Foo.prototype; // Uncaught TypeError: Expecting a function in instanceof check, but got #<Foo>

Bar; // Object {prototype: Object}

Foo; // function Foo() {}

Bar.prototype; // Object {key: "fooValue"}

Foo.prototype; // Foo {key: "fooValue"}

Bar.prototype instanceof Foo; // true

Some debugging code to help you understand better.

Here is the "regular" way of writing objects in Javascript:
Code:
// -----------------------------------------
function Foo() {};
Foo.prototype.key = 'fooValue';

var Bar = new Foo();
// -----------------------------------------

Bar; // Foo {key: "fooValue"}

Bar.prototype; // undefined

Foo; // function Foo() {}

Foo.prototype; // Foo {key: "fooValue"}

Bar instanceof Foo; // true

// Note that you can't check Bar.prototype instance because it is undefined

Then you must realise that Bar.prototype seems to be the object you want (is most alike) the Bar object instance that you desire.

However, consider this - we give Foo objects a new data field now:

Code:
// ------------------------------------------
function Foo() {
  this.x = 0;
}

Foo.prototype.key = 'fooValue';

var Bar = Object.create(Foo.prototype);
// ------------------------------------------

Bar; // Object {key: "fooValue"}

Bar instanceof Foo; // true

Clearly, it is missing the 'x' data field that defines the object - despite whatever instanceof value it might have.

On the other hand, the "classical" method:

Code:
// ------------------------------------------
function Foo() {
  this.x = 0;
}

Foo.prototype.key = 'fooValue';

var Bar = new Foo();
// ------------------------------------------

Bar; // Foo {x: 0, key: "fooValue"}

Bar.prototype; // undefined

Bar instanceof Foo; // true
 

KnightNiwrem

Senior Member
Joined
Jun 1, 2014
Messages
1,057
Reaction score
0
I just did that to demonstrate how 'new' doesn't instantiate an object like new would in say, Java or PHP - coz you can't execute a class in classical OO languages. But in JS, when you use new, you call the constructor function too, and if it happens to change state on some other variable that isn't in its scope, then that leads to unexpected consequences.

So that's why all along I always used Object.create. As for the other stuff, I'm going to set up a couple of experimental fiddles and report back...but just off the top of my head, why would instanceOf not work? var Bar = Object.create(Foo) followed by Bar.prototype = Object.create(Foo.prototype)...would Bar instanceOf Foo not return true? And then Bar.prototype instanceOf Foo.prototype == true

You also need to understand why side-effect happens for your particular code - it has to do with the difference in the environment/variable-mapping model in Javascript and, say, Java.

Function Objects in Javascript declared in the global environment, for better or for worse, points to the global environment. This has its advantages, which we will not go into, here. When reading a variable, it looks for the variable in the local scope, then it goes up and up and up until it finds it or it can't go up anymore.

For your code:
Code:
var Bar = "Foo";

function mutate() {
    Bar = "FooBar";
}

var newMutate = new mutate();

// ----------------------------------

Bar; // FooBar

First, when Mutate is called, it looks for Bar in its own scope to assign the value "FooBar". Since it doesn't find it, it goes up to the global environment, finds the variable Bar and mutates it.

One easy workaround is to use this.Bar, instead, in the mutate() function. This assigns a new data field, Bar, to new mutate objects.

If that is not what you want, you can use declaration of variables, instead of variable assignment, to achieve no side-effect without adding a new data field to every new mutate object.

Consider this instead:
Code:
var Bar = "Foo";

function mutate() {
    var Bar = "FooBar";

    // Further reference of variable Bar will use the function's Bar (that is, "FooBar") until the function "ends"
}

var newMutate = new mutate();

// ----------------------------------

Bar; // Foo

There is no assignment of data fields here - when mutate is done calling, the variable Bar that is in mutate's calling environment disappears/terminates.

Naturally, in both cases, newMutate is an empty object because the code neither assigns any data field nor methods.

Finally, you should be pleased to hear that, newMutate instanceof mutate === true, as expected.
 

godchuanz

Senior Member
Joined
Nov 14, 2004
Messages
530
Reaction score
0
For all aspiring JavaScript coders, Douglas Crockford's series of videos is a must-watch. Catch the first part here:


His selective use of the language turns off some people, but is actually very well-thought. In fact, most of his recommendations on how to code, and how avoid pitfalls actually make it into the language standards. For example, people are increasingly staying away from "new" in favour of Object.create that he advocates.

He also has a pretty sensible take on the new ES-6 features in another video. Most significant of which, he believes adding class is a mistake.
 

KnightNiwrem

Senior Member
Joined
Jun 1, 2014
Messages
1,057
Reaction score
0
For all aspiring JavaScript coders, Douglas Crockford's series of videos is a must-watch. Catch the first part here:

His selective use of the language turns off some people, but is actually very well-thought. In fact, most of his recommendations on how to code, and how avoid pitfalls actually make it into the language standards. For example, people are increasingly staying away from "new" in favour of Object.create that he advocates.

He also has a pretty sensible take on the new ES-6 features in another video. Most significant of which, he believes adding class is a mistake.

You might want to take a look at this and this (pun intended).

The second link explains how object and its constructors *should* be properly written to avoid most of the pitfalls experienced by TS.
 

natnai

Supremacy Member
Joined
Nov 6, 2007
Messages
8,020
Reaction score
1
You also need to understand why side-effect happens for your particular code - it has to do with the difference in the environment/variable-mapping model in Javascript and, say, Java.

Function Objects in Javascript declared in the global environment, for better or for worse, points to the global environment. This has its advantages, which we will not go into, here. When reading a variable, it looks for the variable in the local scope, then it goes up and up and up until it finds it or it can't go up anymore.

For your code:
Code:
var Bar = "Foo";

function mutate() {
    Bar = "FooBar";
}

var newMutate = new mutate();

// ----------------------------------

Bar; // FooBar

First, when Mutate is called, it looks for Bar in its own scope to assign the value "FooBar". Since it doesn't find it, it goes up to the global environment, finds the variable Bar and mutates it.

One easy workaround is to use this.Bar, instead, in the mutate() function. This assigns a new data field, Bar, to new mutate objects.

If that is not what you want, you can use declaration of variables, instead of variable assignment, to achieve no side-effect without adding a new data field to every new mutate object.

Consider this instead:
Code:
var Bar = "Foo";

function mutate() {
    var Bar = "FooBar";

    // Further reference of variable Bar will use the function's Bar (that is, "FooBar") until the function "ends"
}

var newMutate = new mutate();

// ----------------------------------

Bar; // Foo

There is no assignment of data fields here - when mutate is done calling, the variable Bar that is in mutate's calling environment disappears/terminates.

Naturally, in both cases, newMutate is an empty object because the code neither assigns any data field nor methods.

Finally, you should be pleased to hear that, newMutate instanceof mutate === true, as expected.

Thank you so much man. Seriously. You saved me hours of time.

After spending a long time in EDMW, this thread gives me hope. Hope that not everybody in the world is stupid.
 

nexusfanboi

Member
Joined
Nov 26, 2012
Messages
447
Reaction score
0
Thank you so much man. Seriously. You saved me hours of time.

After spending a long time in EDMW, this thread gives me hope. Hope that not everybody in the world is stupid.

That is because this isn't EDMW.

Have a look at https://www.udacity.com/course/object-oriented-javascript--ud015

I think you will find the whole course very useful. It starts with the scoping that I feel you don't have a grip on, and continues to develop on various OO styles in JS.
 

natnai

Supremacy Member
Joined
Nov 6, 2007
Messages
8,020
Reaction score
1
Ok so after reading the two articles and having a little mess about with KnightNiwrem's very enlightening snippets, I have settled on:

Code:
var Foo = {
    bar: function () { console.log('FooBar') }
};

var Bar = Object.create(Foo);

var Test = Object.create(Bar);

console.log(Bar.isPrototypeOf(Test)); // true
console.log(Foo.isPrototypeOf(Test)); // true

Test.bar(); // FooBar

Because my puny brain doesn't want to deal with .prototype and .constructor properties and instanceof. I think this seems to be quite a clean way of determining of whether any two given objects share functionality (i.e. whether Bar can delegate to Foo and whether Test in turn can delegate to Bar and Foo). Is there anything wrong with what I'm doing? It also seems to get around the whole weirdness of .prototype being created on 'instance' objects.
 

natnai

Supremacy Member
Joined
Nov 6, 2007
Messages
8,020
Reaction score
1
That is because this isn't EDMW.

Have a look at https://www.udacity.com/course/object-oriented-javascript--ud015

I think you will find the whole course very useful. It starts with the scoping that I feel you don't have a grip on, and continues to develop on various OO styles in JS.

Thanks man, just signed up for the course. Good share. I think I understand scope (i.e. inner function access to outer scope but not vice versa) and by extension closures in JS, but what I am struggling with is definitely the internal [[Prototype]] property on objects. I really, really, REALLY don't like it. Why can't it just be classes and instances like PHP?? :(
 

KnightNiwrem

Senior Member
Joined
Jun 1, 2014
Messages
1,057
Reaction score
0
Thanks man, just signed up for the course. Good share. I think I understand scope (i.e. inner function access to outer scope but not vice versa) and by extension closures in JS, but what I am struggling with is definitely the internal [[Prototype]] property on objects. I really, really, REALLY don't like it. Why can't it just be classes and instances like PHP?? :(

If you really, really, REALLY dislike prototypal Object-oriented programming in Javascript, I do have an idea on how you can "help" it.

First off, about your code, it does seem like an interesting way to go about it. However, I'm not entirely sure how you would distinguish Objects from Classes now (I'm using these terms loosely - there aren't exactly Classes in Javascript).

Note that any modification to Foo.bar would affect Test.bar and Bar.bar. On the other hand, assigning Bar.bar to something else only affects Test.bar because it erases the value of Bar.bar (which is a reference to Foo.bar) and assigns it something else. Test.bar, following the prototypal chain, references Bar.bar, and thus, is affected.

Code:
var Foo = { 
  bar: function () {
           console.log('FooBar') 
         } 
}; 

var Bar = Object.create(Foo); 
var Test = Object.create(Bar);

Bar.bar === Foo.bar; // true

This is, actually, a good thing for methods. We want methods to reference their parent's methods - and for any override to only influence the overridden class' methods and its children.

However, this is not a good thing for instance data fields (or values). We want every object instance to have a unique value (or state) that they keep track of.

This is the classical idea of Object-oriented programming that we are familiar with.

------

Next, you would be pleased that in ECMAscript 6, they are trying to introduce some syntactic sugar (classes, extends and static).

------

Finally, in CS1101S (where we use a slightly modified version of Javascript), Objects Inheritance and construction was slightly modified to resemble a more classical form of Object-oriented programming.

First, let us consider this piece of Java code:

Code:
// This describes a TwoDimensionalCoodinate Class
class TwoDimensionalCoordinate {
    
    // public (not good design, but we'll leave it for now) data fields
    public int x;
    public int y;

    // public constructor takes in 2 parameters
    public TwoDimensionalCoordinate(int x, int y) {
        this.x = x;
        this.y = y;
    }

    // public method for incrementing x and y
    public void incrementX() {
        this.x = this.x + 1;
    }

    public void incrementY() {
        this.y = this.y + 1;
    }
}

// This describes a ThreeDimensionalCoordinate class that extends TwoDimensionalCoordinates
class ThreeDimensionalCoordinate extends TwoDimensionalCoordinates {

    // public data field
    public int z;

    // public constructor for ThreeDimensionalCoordiante
    public ThreeDimensionalCoordinate(int x, int y, int z) {
        super(x, y); // Note: This is required (and must be the first line in a constructor), but Java "helps" put this in if you "forgot"
        this.z = z;
    }

    // public methods for incrementing z
    public void incrementZ() {
        this.z = this.z + 1;
    }

    @override
    // public method for incrementing x is faster in ThreeDimensionalCoordinates
    public void incrementX() {
        this.x = this.x + 2;
    }

class SandBoxMain {
	
  public static void main(String args[]) {
		
    TwoDimensionalCoordinate xy = new TwoDimensionalCoordinate(3, 5);
		
    ThreeDimensionalCoordinate xyz = new ThreeDimensionalCoordinate(4, 7, 8);
			
    xy.incrementX(); // 3 becomes 4
    xy.incrementY(); // 5 becomes 6
		
    xyz.incrementX(); // Overridden method; 4 becomes 6
    xyz.incrementY(); // Inherited method; 7 becomes 8

    System.out.println(xy.x);
    System.out.println(xy.y);
		
    System.out.println(xyz.x);
    System.out.println(xyz.y);
    System.out.println(xyz.z); // This instance has a z parameter
  }
}

As you can see from the above (WOT) snippet, we have classes, constructors, and the extends keyword.

Java creates new classes using the new keyword and by calling the constructor with a function call-like syntax. Inside the parenthesis, we put in the arguments required for the constructor.

Most people are familiar with the above style. Excellent. In CS1101S, we attempt to change the declaration of Objects such that it resembles a class, constructor and extending model too.

The final "product" looks like this:
Code:
// This serve as the "constructor" for the "class"
function TwoDimensionalCoordinate(x, y) {

  // ALL class-related [B]parameters-only[/B] uses this.<parameter>
  // ALL data fields that are NOT STORED uses var keyword
  this.x = x;
  this.y = y;
}

// ALL class-related [B]methods-only[/B] go into the prototype
TwoDimensionalCoordinate.prototype.incrementX = function() {
  this.x = this.x + 1;
};

TwoDimensionalCoordinate.prototype.incrementY = function() {
  this.y = this.y + 1;
};

function ThreeDimensionalCoordinate(x, y, z) {

  // This is the mandatory super(x, y);
  // Here, we[B] demand[/B] you write this line (if inheriting) in the[B] first[/B] line of your subclass constructor
  TwoDimensionalCoordinate.call(this, x, y);

  // data fields
  this.z = z;
}

// We also need the "extends" keyword to tell the program that ThreeDimensionalCoordinate is a subclass of TwoDimensionalCoordinate
ThreeDimensionalCoordinate.Inherits(TwoDimensionalCoordinate);

ThreeDimensionalCoordinate.prototype.incrementZ = function() {
  this.z = this.z + 1;
};

// Overriding methods for subclasses is completely the same as declaring methods
ThreeDimensionalCoordinate.prototype.incrementX = function() {
  this.x = this.x + 2;
};

var xy = new TwoDimensionalCoordinate(3, 5);
var xyz = new ThreeDimensionalCoordinate(4, 7, 8);

xy.incrementX(); // 3 becomes 4
xy.incrementY(); // 5 becomes 6

xyz.incrementX(); // override; 4 becomes 6
xyz.incrementY(); // inherited; 7 becomes 8

xy.x;
xy.y;

xyz.x;
xyz.y;
xyz.z; // This instance has a z parameter

// Extra checks
xy instanceof TwoDimensionalCoordinate; // true
xy instanceof ThreeDimensionalCoordinate; // false

xyz instanceof TwoDimensionalCoordinate; // true
xyz instanceof ThreeDimensionalCoordinate; // true

As you can see, if we can achieve the above, Objects in javascript will look very... classical.

We get the instance parameter independence that we are familiar with - changing xy.x doesn't change xyz.x. And we get the method chaining that we are familiar with (this helps with speed) - before we override ThreeDimensionalCoordinate.incrementX, ThreeDimensionalCoordinate.incrementX === TwoDimensionalCoordinate.incrementX. Hence, if we change the parent classes' implementation of incrementX, it correctly modifies its children classes' implementations too. On the other hand, changing the children's implementation does not affect the parent in any way.

Now, I do not claim I know how the CS1101S team did it, but I guessed (reverse-engineered) that they probably included a line of code right at the start of the Javascript code:

Code:
Function.prototype.Inherits = function(parentObj) {
  this.prototype = Object.create(parentObj.prototype);
};

That's all. If you insert this snippet right at the top of the above javascript snippet, you get the behavior desired.

Now, I'm pretty sure some of the programmers here would immediately come in to denounce such blasphemy - extending natives are frowned upon by some.

Also, note that this method does not support multiple inheritance (not that I think much people would use it).

Finally, when using such a solution, you want to very carefully brief collaborators to avoid "Inherits" like it is a reserved keyword. If someone created another function with parameter this.Inherits = <something else>;, you might run into trouble with "subclasses" of this function.

-------------

On a closing note, about concerns related to confusion between function calls and Object instance calls.

I'd suggest you use standards. For example, most programmers capitalize the first letter of the class name, while they don't capitalize the first letter of a function name. The name, thus, represents our intention for creating that function.

Therefore:

Code:
var a = new twoblahblah(3, 4); // This will ring alarm bells (named like a function - should not have new)

var b = Twoblahblah(3, 4); // This will ring alarm bells (named like a class - should have new)

------------------

Credits for Ideas: CS1101S team from NUS SoC
 
Last edited:

KnightNiwrem

Senior Member
Joined
Jun 1, 2014
Messages
1,057
Reaction score
0
Quick Summary for previous post:

Put this in Line 1 of code:
Code:
Function.prototype.Inherits = function(parentObj) {
  this.prototype = Object.create(parentObj.prototype);
};

Parameters go into constructor:
Code:
function Foo(arg1, arg2) {
  this.x = arg1;
  this.y = arg2;
}

Methods go into class.prototype:
Code:
Foo.prototype.changeX = function(newX) {
  this.x = newX;
};

Child constructor MUST call parent constructor first (and pass all parameters that parent constructor accepts):
Code:
function Bar(arg3, arg4, arg5) {

  // 'this' is the first parameter; followed by parameters accepted by parent constructor
  Foo.call(this, arg3, arg4);

  this.z = arg5;
}

Children classes MUST inherit/extend from parent classes first:
Code:
Bar.Inherits(Foo); // Inherit before declaring/overriding methods

Bar.prototype.changeZ = function(newZ) {
  this.z = newZ;
};

Create instances of an Object by calling the Class constructor using new:
Code:
var tester = new Foo("myX", "myY");

Name functions by starting with small letters; Name "classes/constructors" by starting with capitalized letters:
Code:
function add(x, y) {
  return x + y;
}

function MyNumber(value) {
  this.value = value;
}

var a = new add(1, 2); // RINGS ALARM BELLS
var b = MyNumber(3); // RINGS ALARM BELLS

------------------------

Moral of the story in programming paradigms and philosophy:

Incorporating standards and rules on how you program can make programming a much easier and intuitive task.

That doesn't mean you should restrict yourself to a small programming methodology for a highly flexibly language, however. Understand that studying the workings behind it remains important, and when your programming paradigm fails for some problem, it might be time to try a different paradigm for that particular problem, applying what you know about how all this flexibility is created.
 
Last edited:

natnai

Supremacy Member
Joined
Nov 6, 2007
Messages
8,020
Reaction score
1
Quick Summary for previous post:

Put this in Line 1 of code:
Code:
Function.prototype.Inherits = function(parentObj) {
  this.prototype = Object.create(parentObj.prototype);
};

Parameters go into constructor:
Code:
function Foo(arg1, arg2) {
  this.x = arg1;
  this.y = arg2;
}

Methods go into class.prototype:
Code:
Foo.prototype.changeX = function(newX) {
  this.x = newX;
};

Child constructor MUST call parent constructor first (and pass all parameters that parent constructor accepts):
Code:
function Bar(arg3, arg4, arg5) {

  // 'this' is the first parameter; followed by parameters accepted by parent constructor
  Foo.call(this, arg3, arg4);

  this.z = arg5;
}

Children classes MUST inherit/extend from parent classes first:
Code:
Bar.Inherits(Foo); // Inherit before declaring/overriding methods

Bar.prototype.changeZ = function(newZ) {
  this.z = newZ;
};

Create instances of an Object by calling the Class constructor using new:
Code:
var tester = new Foo("myX", "myY");

Name functions by starting with small letters; Name "classes/constructors" by starting with capitalized letters:
Code:
function add(x, y) {
  return x + y;
}

function MyNumber(value) {
  this.value = value;
}

var a = new add(1, 2); // RINGS ALARM BELLS
var b = MyNumber(3); // RINGS ALARM BELLS

------------------------

Moral of the story in programming paradigms and philosophy:

Incorporating standards and rules on how you program can make programming a much easier and intuitive task.

That doesn't mean you should restrict yourself to a small programming methodology for a highly flexibly language, however. Understand that studying the workings behind it remains important, and when your programming paradigm fails for some problem, it might be time to try a different paradigm for that particular problem, applying what you know about how all this flexibility is created.

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.

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.
 
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