constructor function closure variable [duplicate] - javascript

This question already has answers here:
Assigning prototype methods *inside* the constructor function - why not?
(6 answers)
Closed 6 years ago.
For the following function I was expecting a and b to have their own versions of array, hence expecting the output to be false, but it prints true. Can anyone please explain, why ?
function Test() {
var a = [1,2,3];
Test.prototype.getArray = function() { return a; };
}
var a = new Test();
var b = new Test();
console.log(a.getArray() === b.getArray());

Every Test object inherits the same prototype. The exact same prototype. Since you're overwriting a prototype function, it's overwriting it for all objects of that type.
Example:
function log(msg) {
document.querySelector('pre').innerText += msg + '\n';
}
function Person(name) {
this.name = name;
}
Person.prototype.sayHello = function() {
log('Hello, ' + this.name);
};
var bob = new Person('Bob');
var alice = new Person('Alice');
bob.sayHello();
alice.sayHello();
// Overwriting the prototype function
Person.prototype.sayHello = function() {
log('Goodbye, ' + this.name);
};
bob.sayHello();
alice.sayHello();
<pre></pre>
If you absolutely need to access private data in a function using a standard constructor, you'll need to define the function within the constructor itself.
function Test() {
var a = [1,2,3];
this.getArray = function() {
return a;
};
}
Be aware that this negates a lot of the space and performance optimizations you gain from prototype inheritance in many implementations.

Related

Is there a way to create and access a method within a standard javascript function? [duplicate]

This question already has answers here:
declare function properties inside
(2 answers)
Adding custom properties to a function
(10 answers)
Closed 1 year ago.
It's possible to create a method like this in a literal object :
https://jsfiddle.net/7q1530sp/2
let o = {
f: function f () {
alert("f")
}
}
o.f();
Since function is also an object, I'd like to be able to do the same within a function I tried this but it doesn't work, is there a way ?
https://jsfiddle.net/7q1530sp/1
function o(){
f: function f () {
alert("f")
}
}
o.f();
You can define as many functions-within-functions as you like!
let f1 = function() {
let f2 = function() {
let f3 = function() {
return 'functions';
};
return 'love ' + f3();
};
return 'I ' + f2();
};
console.log(f1());
If you want to define functions as properties, you could also do the following:
let f1 = function() {
return 'I ';
};
f1.f2 = function() {
return 'love ';
};
f1.f3 = function() {
return 'functions';
};
console.log(f1() + f1.f2() + f1.f3());
Note that this property assignment works exactly the same way that objects work; e.g.
let f1 = function(){}; f1.someProperty = 'someValue';
vs
let o = {}; o.someProperty = 'someValue';
The assignment of properties to a function doesn't need to occur within the function body, but functions certainly could assign properties to themselves:
let f = function() {
f.a = 'b';
f.c = 'd';
};
Note that in this case the f.a and f.c properties wouldn't exist until you actually call the function by performing: f().
You have to define it outside of the function:
function o(){
console.log("o");
}
o.f = function(){
console.log("f");
}
o.f()
You can create objects within a function in Javascript.
Here is your code:
function o() {
const d = {
f: function f() {
alert("f")
},
}
d.f();
}
o();
Output:
https://jsfiddle.net/pLjc0vbf/1/

Function object and Function are they same? [duplicate]

This question already has answers here:
JavaScript difference between function and new function
(2 answers)
Closed 5 years ago.
Is
var myFunc = function() {
}
similar to myFunc = new function () { }
I read in the documentation it says both mean the same. What is the difference between these two?
They are not the same.
var myFunc = function(){} myFunc is a reference to anonymous function expression.
var myFunc = new function (){} reference to newly constructed instance of anonymous function expression.
var myFunc = function() {}
var myFunc1 = new function() {}
// it is the same as doing:
var myFunc2 = new myFunc;
console.log(myFunc, ' and the type is ', typeof myFunc)
console.log(myFunc1, ' and the type is ', typeof myFunc1)
console.log(myFunc2, ' and the type is ', typeof myFunc2)
You can reference this answer as well

Checking whether toString has been assigned [duplicate]

This question already has answers here:
How do I check if an object has a specific property in JavaScript?
(31 answers)
Closed 7 years ago.
I want a debugging output function to contain a test: if the object has a toString function, use it.
But then, every JavaScript object has a toString function, so what I really want is to check whether it has been assigned toString instead of just inheriting a default one.
What's the best way to do this? It occurs to me maybe you could exploit the fact that the inherited function isn't visible in for-in iteration, though it feels like there ought to be an O(1) solution.
something like
obj.hasOwnProperty('toString')
The result of obj.hasOwnProperty('toString') depends on the way how your toString implementation is created. I did some simple test:
function A() {
}
A.prototype.toString = function(){
console.log("A.toString");
};
function B() {
this.toString = function(){
console.log("B.toString");
}
}
var t = [new A(), new B(), new A()];
for(var i=0; i<t.length; i++) {
var hasOwnToString = t[i].hasOwnProperty("toString");
console.log(hasOwnToString);
if(hasOwnToString) {
t[i].toString();
}
}
Result:
false
true
B.toString
false
For A style it's false, but for B style it's true
You can check to see if the toString function is the same as Object (the object all objects descend from)
function hasUserPrototype(obj) {
return Object.getPrototypeOf(obj).toString !== Object.prototype.toString;
}
See Check if an object has a user defined prototype?
function Foo()
{
}
// toString override added to prototype of Foo class
Foo.prototype.toString = function()
{
return "[object Foo]";
}
var f = new Foo();
function Boo()
{
}
var g = new Boo();
function hasUserPrototype(obj) {
return Object.getPrototypeOf(obj).toString !== Object.prototype.toString;
}
document.write(hasUserPrototype(f)); // true
document.write(hasUserPrototype(g)); // false
var x = {}
if (!(x.hasOwnProperty("toString"))) {
x.toString = function() {
return "I am X"
}
}
x.toString()
// "I am X"

How to access class variables from inner prototype - javascript [duplicate]

This question already has answers here:
'this' in function inside prototype function [duplicate]
(8 answers)
Closed 7 years ago.
I might not be clear with my title of the question. Sorry for that.
Here is what I wanted to do.
I'm trying to use prototyping pattern in javascript. I created a class as following.
var MyClass = null;
(function() {
MyClass = function() {
this.clsVar = "I'm inside constructor";
};
MyClass.prototype = {
constructor: MyClass,
myFunc1: function() {
console.log("I'm func1 accessing constructor variable : " + this.clsVar);
},
nested: {
myFunc2: function() {
console.log("I'm func2 accessing constructor variable : " + this.clsVar); // I know, this will never point to the class scope
}
}
}
}())
I'm creating an object.
var my = new MyClass();
my.myFunc1(); // which prints "I'm func1 accessing constructor variable : I'm inside constructor"
my.nested.myFunc1(); // as expected, it prints "I'm func2 accessing constructor variable : undefined
All I am trying to do is, I should be able to access clsVar from nested.myFunc2
is that possible.? Any help is greatly appreciated and needed.
Thanks.
Actually, there is a point.
The this inside your myFunc2 does not refer anymore to MyClass but to another context. So, the fastest way is to do is to use call or apply like:
var myNewObject = new MyClass();
myNewObject.nested.myFunc2.call(myNewObject, arg1, arg2);
or
myNewObject.nested.myFunc2.apply(myNewObject, [arg1, arg2]);
JavaScript's prototype-based class system does not allow this.
MyClass's prototype will be shared between all instances of the class. In the following code, both instances will use the same function instance...
var first = new MyClass(), second = new MyClass();
first.nested.myFunc2(); <-- Same prototype function
seecond.nested.myFunc2(); <-- Same prototype function
When the code enters the "myFunc2" definition, which parent should it be accessing?
If you need access to the parent's "this" value, you'll have to use a closure and set up the nested object in the parent constructor as below.
var MyClass = null;
(function() {
MyClass = function() {
this.clsVar = "I'm inside constructor";
var that = this;
this.nested = {
myFunc2: function() {
console.log("I'm func2 accessing constructor variable : " + that.clsVar); // I know, this will never point to the class scope
}
}
};
MyClass.prototype = {
constructor: MyClass,
myFunc1: function() {
console.log("I'm func1 accessing constructor variable : " + this.clsVar);
}
}
}())

JavaScript function currying does not work on instance method

I am learning function currying in JavaScript by reading online and writing some simple code. I got following example in online article
function toArray(obj) {
return Array.prototype.slice.call(obj);
}
Function.prototype.curry = function() {
if (arguments.length<1) {
return this; //nothing to curry with - return function
}
var __method = this;
var args = toArray(arguments);
return function() {
return __method.apply(this, args.concat(toArray(arguments)));
}
}
var add = function(a,b) {
return a + b;
}
var addTen = add.curry(10); //create function that returns 10 + argument
alert(addTen(20)); //alerts 30 correctly
Then I tried to try it on the method of an instantiated function. So I tried following. But it gave me error "Unable to get property 'prototype' of undefined or null reference" on the second last line. I know this error is nothing to do with currying but I am messing up with some basics of JS functions concept. So where I am going wrong.
function Person()
{
this.age = 15;
}
Person.ageAfter = function (years) {
return this.age + years;
}
var personObj = new Person();
var ageAfterFiveYears = personObj.ageAfter.prototype.curry(5); //**Error**
alert(ageAfterFiveYears());
You have two issues:
The ageAfter function is not an instance method - you've added it to the "class" (i.e. it's kind of like a static method). It should be added to the prototype.
When you curry the function you lose your object's context, so you either need to rebind the context
e.g:
var ageAfterFiveYears = Person.prototype.ageAfter.curry(5).bind(personObj);
giving you a function that only works on the current instance, or better yet, as #Pointy suggests in the comments, you should just put the curried function back onto the prototype:
Person.prototype.ageAfterFiveYears = Person.prototype.ageAfter.curry(5);
which then adds the .ageAfterFiveYears method to every Person object.
You shouldn't include the prototype in your call:
var ageAfterFiveYears = personObj.ageAfter.curry(5);
The "ageAfter" property has a function for its value, so that function will have access to your "curry" function just like the function in your first example.
When you call it on the prototype, the value of this inside your function will be the prototype object, not the "ageAfter" function.
Also as a comment points out, you need to put "ageAfter" on the prototype:
Person.prototype.ageAfter = function(years) { ... }
edit — the binding issue that Alnitak points out is also important. (When I say "important", what I mean is "necessary to make your code work".)
Curry will not work for your use case. You need to bind the context so this is your personObj.
function Person() {
this.age = 15;
}
Person.prototype.ageAfter = function (years) {
return this.age + years;
}
var personObj = new Person();
var ageAfterFiveYears = personObj.ageAfter.bind(personObj, 5);
alert(ageAfterFiveYears());

Categories