I'm a C++ programmer who recently landed on the JavaScript world; now I'm trying to apply some of the dessign patterns of C++ to JavaScript for the sake of my understanding and mental health.
AFAIK, the following codes are kind of equivalent in C++ and Javascript:
// Class definition
template <typename T> class foo
{
public:
// Constructor
foo(T value) { this->value = value; }
// Public function
T twice() { return this->value + this->value; }
private:
// Private function
void bar() { }
// Private member
T value;
};
// "Class" definition and constructor
function foo(value)
{
// "Private" member
this.value = value;
// "Private" function
this.bar = function() { };
}
// Public function
foo.prototype.twice = function() { return this.value + this.value; };
The usage of both classes are similar too:
foo<int> f1(1);
foo<std::string> f2("1");
std::cout << f1.twice() << '\n'; // output: 2
std::cout << f2.twice() << '\n'; // output: 11
var f1 = new foo(1);
var f2 = new foo('1');
print(f1.twice()); // output: 2
print(f2.twice()); // output: 11
But there's a thing that cannot be done with a JavaScript class and is possible to do with a C++ class: the use of a temporary RValue to do a task:
std::cout << foo<float>(3.14f).twice() << '\n'; // output: 6.28
print(foo(3.14).twice()); // Uncaught TypeError: undefined is not a function
I think that the error on the JavaScript version is due to the fact that foo is a function and it returns nothing (undefined
), so at first I was thinking of change the constructor with the code below:
// "Class" definition and constructor
function foo(value)
{
// "Private" member
this.value = value;
// "Private" function
this.bar = function() { };
return this; // <----- new code!
}
But this doesn't work at all; the object returned by the return this;
instruction isnt of type foo
(foo(3.14) instanceof foo
is false
).
While debugging in Chrome 35.0.1916.114 the type of this
in the instruction return this;
is foo
but the type changes to window
in this situation:
var x = foo(3.14); // x is typeof window
Once made the introduction, here comes the questions:
this
is foo
inside the constructor and window
when captured outside?
new
operator isn't used?In JavaScript, when you use the new
keyword with a function, the function behaves differently to when called without the new
keyword. With it, the function acts like a class, and a new object is instantiated from it, just like in traditional OOP languages. Additionally, the this
context is set to itself and the return value of the function is disregarded.
By contrast, without the new
keyword, the this
context is set to the global scope, which for browsers is the window
object, and the return value can be captured by whatever called it.
It is possible to create something like your C++ example, whereby you don't need the new
keyword, and it still returns a new object.
Fiddle
function foo(value) {
function foo(value) {
this.value = value;
this.bar = function () {};
this.twice = function() { return this.value + this.value; }
}
return new foo(value);
}
console.log( foo(3.14).twice() ); // 6.28
the outer function foo
behaves like a normal function, and is intended to be called without the new
keyword. Inside lives the inner foo
, which is intended to be like a class - called with the new
keyword. The outer foo
instantiates a new instance of the inner foo
and returns it. Thus it can be used like the C++ example. It is not necessary to declare the class-like function within the outer function, it just depends if you want to encapsulate it within the outer.
The two examples in the question are not exactly equivalent because the JavaScript example uses all public properties and methods, whereas the C++ example has bar
and value
as private.
Below is a version that is closer to the C++ version:
Fiddle
function foo(value) {
function foo(value) {
var value = value;
function bar(){}
this.twice = function() { return value + value; }
}
return new foo(value);
}
console.log( foo(3.14).twice() ); // 6.28
console.log( foo(3.14).value ); // undefined because it's private
console.log( foo(3.14).bar() ); // undefined because it's private
As you can see from the test cases, value
and bar
are not publicly accessible/visible. This is achieved by not using the this
prefix and declaring value
using the var
keyword (which defines a local variable). The function is declared as a declaration instead of an expression. In JavaScript, there is no formal way of declaring/differentiating public and private properties or methods like in OOP languages.
You may have noticed the above examples don't use prototype to declare any methods. The reason for this is that the prototype way would always declare methods with public visibility, and prototype methods cannot see any variables from inside the "class" or function. The code comments in the question suggest that using this.bar
inside the function body makes it private, but that isn't the case.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With