Javascript new with hard binding - javascript

I have the following code snippet
function foo(a) {
this.a = a;
}
var obj = {a: 77};
var bar = function() {
return foo.apply( obj, arguments );
};
var o = new bar( 2 );
console.log( o.a ); // I think it's 2(why is it undefined?)
console.log(obj.a); // obj.a changed to 2, got it.
Why is o.a undefined? also if I delete the return keyword in bar, it will still be the same.
function foo(a) {
this.a = a;
}
var obj = {a: 77};
var bar = function() {
foo.apply( obj, arguments );
};
var o = new bar( 2 );
console.log( o.a ); // I think it's 2(why is it undefined?)
console.log(obj.a); // obj.a changed to 2, got it.
The question is actually what happens when hard binding and new binding happens the same time

Using new will create a new object and assign that object as this to the function you call it on. In your case, you're not using the new object and instead are calling a function setting obj as this.
As to why adding and removing return doesn't change anything is because in both cases, you're returning undefined. When a function is called with new and returns undefined (a.k.a the default return value) it returns the new object generated by new.
To quote MDN:
The object returned by the constructor function becomes the result of the whole new expression. If the constructor function doesn't explicitly return an object, the object created in step 1 is used instead. (Normally constructors don't return a value, but they can choose to do so if they want to override the normal object creation process.)
So you create a new object but manipulate an old object. Your code effectively works like this.
function foo(a) {
this.a = a;
}
var obj = {a: 77};
var bar = function() {
return foo.apply( obj, arguments );
};
var o = {}; // Originally you used `new` to create a new object
bar(2); // Since `bar` doesn't use `this`, it's the same as if it were called by itself
console.log(o.a); // Empty object
console.log(obj.a); // Modified by `bar`

You have to return this from foo(a), like so:
function foo(a) {
this.a = a;
// "this" NEEDS TO BE RETURNED, OTHERWISE (bar)'s
// VALUE WILL BE UNDEFINED, THUS o.a WILL BE UNDEFINED
return this;
}
var obj = {a: 77};
var bar = function() {
// MAKE SURE THIS IS RETURNED AS WELL
return foo.apply( obj, arguments );
};
var o = new bar( 2 );
console.log( o.a ); // I think it's 2(why is it undefined?)
console.log(obj.a); // obj.a changed to 2, got it.
The question is actually what happens when hard binding and new
binding happens the same time
In this case nothing because a new instance of new bar( 2 ) is useless when its return value is dependent on foo(a), and foo(a) is dependent on a singleton (obj).
I hope that helps!

Related

Object is empty when a property to the prototype of function is added via Object.setPrototypeOf()

Let's consider the following code,
let f = function () {
this.a = 1;
this.b = 2;
}
let o = new f();
f.prototype.c = 3;
console.log(Object.getPrototypeOf(o));
Prints
[object Object] { c: 3 }
But if I use setPrototypeOf instead of f.prototype.c, the object is empty.
let f = function () {
this.a = 1;
this.b = 2;
}
let o = new f();
Object.setPrototypeOf(f, {c: 3});
console.log(Object.getPrototypeOf(o));
Prints
[object Object] { ... }
But if I use
let f = function () {
this.a = 1;
this.b = 2;
}
let o = new f();
Object.setPrototypeOf(f, {c: 3});
console.log(Object.getPrototypeOf(f));
Prints
[object Object] { c: 3 }
In short the question is, when using Object.setPrototypeOf(o), the Object prints empty,
and when using Object.setPrototypeOf(f), the objects prints the property which is added.
where as when setting prototype using f.prototype.c = 3, it is accessible by both Objects
prototype and the functions prototype.
When you Object.setPrototypeOf(f, ... ), the chain is actually 3 long:
The prototype of o is f. The prototype of f is {c:3}.
So your examples are not equivalent to each other:
1)
In the first example, you add the property c directly to the prototype that instances of f will use, so the proto of o contains c since f is the constructor for o.
In the last two examples you add c to the proto of f, so the prototype f was created with. Remember that functions are also just objects and that you're setting the proto of a function you use as a constructor. So the proto of o contains the proto of f which contains c.
2)
In the 2nd example, you getPrototypeOf() o.
In the 3rd, you getPrototypeOf() f. Hence only the 3rd example shows c again.
3)
If you inspect the element in chrome, you see that the constructor of the 2nd example is f, since you ask the proto of o.
In the 3rd example you'll see that the constructor is Object, since you ask the proto of f, which has been set to the object {c} and skip the proto from o to f.
PS: I'm aware this is might be a confusing explanation.
PPS: If you want inheritance, sticking to child.prototype = Object.create( parent.prototype ); child.constructor = child; or ES6 class class child extends parent when it can be used led to the least confusion for me personally.
var first = function first() {
this.value = 'first function';
};
// before .prototype.extra, first inherist from Function.
console.log( 'constructor of first before:', first.constructor );
first.prototype.extra = 'implemented with .prototype.extra';
// after .prototype.extra, first still inherits from Function, we did not change anything to first itself.
console.log( 'constructor of first after:', first.constructor );
// When first is used as a prototype, the instances will get "extra".
// Aka, everything that inherist from first.
var first_instance = new first();
console.log( 'extra on instance of first:', first_instance.extra );
// f itself does NOT have the extra property, only instances of first do.
console.log( 'extra on first itself:', first.extra );
console.log( '------' );
var second = function second() {
this.value = 'second function';
};
// before setPrototypeOf, second inherist from Function, like above.
console.log( 'constructor of second before:', second.constructor );
Object.setPrototypeOf( second, { extra: 'implemented with .setPrototypeOf()' });
// after setPrototypeOf, second inherist from Object, we broke the default inheritance chain.
console.log( 'constructor of second after:', second.constructor );
// BY doing this, we effectively turned second into an object.
// It no longer is a function, so we cannot use function methods like .call() or .apply()
console.log( 'second is object, not function: function.apply', second.apply );
console.log( 'second is object, not function: object.hasOwnProperty', second.hasOwnProperty );
// When second is used as a prototype, the instances will not get "extra".
var second_instance = new second();
console.log( 'extra on instance of second:', second_instance.extra );
// second itself Does have the extra property, sine we assigned it on the prototype used by second. not when second is used as the prototype.
console.log( 'extra on second itself:', second.extra );

Javascript and this?

Something is troubling me with the 'this' Object in Javascript.
So 'this' can be defined has a property belonging to the execution context.
And when we call a function from a specific context, 'this' will be defined by the callee.
Now let's suppose I got this code:
function f4(){
this.herp = "derp";
this.test = '2';
}
function Thing(){
this.prop1="nothingSpecial";
this.test = '1';
f4();
f4.call(this);
}
var thing = new Thing();
console.log('herp:'+thing.herp);
console.log('test:'+thing.test);
In the code below, If i hadn't add f4.call(this), thing.herp would be undefined. According to me, f4() and f4.call(this) is the same in the context of the Thing function but it's not the case.
1. if the function is called with the new keyword this will point to the newly constructed objects
function fun() { this.a = 3; }
var obj = new fun();
console.log(obj.a); // 3
2. if we use hard binding (bind function) this will point to object that we pass in bind function argument
function fun1() { this.a = 3; }
var obj1 = { a: 0 };
var fun2 = fun1.bind(obj1);
fun2();
console.log(obj1.a); // 3
now, when we call fun2 this keyword will point to obj1, even when we assign fun2 to another object and call from it using a dot notation
var obj2 = { a: 0, fun: fun2 };
obj2.fun();
console.log(obj2.a) // 0
but when we use fun2 as a constructor with the new keyword, in that case this will point to the newly created object, we can say that new keyword is stronger than hard binding
function fun1() { this.a = 3; }
var obj1 = { a: 0 };
var fun2 = fun1.bind(obj1)
var obj2 = new fun2()
console.log(obj1.a) // 0
console.log(obj2.a) // 3
3. If we call function using a call or apply function this will point to object which we passed in function arguments.
function fun() { this.a = 3; }
var obj = {a: 0};
fun.call(obj);
console.log(obj.a); // 3
4. If we call function directly from object using a dot notation this will point to that object
function fun() { this.a = 3; }
var obj = {a: 0, fun: fun};
obj.fun();
console.log(obj.a); // 3
5. In almost every other cases this will point to global object
Now let's go to your example
function f4(){
this.herp = "derp";
this.test = '2';
}
function Thing(){
this.prop1="nothingSpecial";
this.test = '1';
f4();
f4.call(this);
}
var thing = new Thing();
console.log('herp:'+thing.herp);
console.log('test:'+thing.test);
When you use Thing() as a constructor with new keyword, this inside a Thing function point to newly created object (lets assume for simplicity that point to thing, but in real new operator creates a new object, then use a constructor function to set it up and at end assign this object to thing)
As a this point to thing object you created a two variables inside of thing - prop1 and test:
thing = {
prop1: "nothingSpecial",
test: "1"
}
then when you call f4 for the the first time this inside of it points to global, it is no matter that f4 is called insiade of Thing function. So you set 2 global variables herp and test. At this point there is no thing.herp variable so when you tried to log it out, console prints undefined.
thing = {
prop1: "nothingSpecial",
test: "1"
}
// global objects
console.log(test) // 2
console.log(herp) // "derp"
Next, you called f4 using a call function, so you passed this from Thing to f4, as this in Thing point to thing object, this in f4 also point to thing object, so now f4 function created new variable herp inside of thing and overwrite test from '1' to '2'
thing = {
prop1: "nothingSpecial",
test: "2",
herp: "derp"
}

Is this proper javascript for making a namespace that encapsulates various methods into different objects?

var namespaced = {
A: function(){
function r(){
//do some stuff
return something;
}
var someProperty = 5;
function j(){
//do some more stuff
return something;
}
},
B: function(){
//can I call A and C?
A.r();
C.d();
},
C: function(){
function d() {
//do stuff we like
}
}
}
Then I could do...
namespaced.A.j();
namespaced.C.d();
something = namespaced.A.someProperty;
right?
Would I need to do this too?
var something = new namespaced.A()?
If so does A() have a constructor? I'm really confused here :{
I'm trying to encapsulate my javascript so it's easy to maintain
Then I could do...
namespaced.A.j();
namespaced.C.d();
something = namespaced.A.someProperty;
No you couldn't. The function j and someProperty are only local to A and are not propagated to the outside. If you want to access them from the outside, you have to make them a property of the function, using this:
var namespaced = {
A: function(){
this.r = function(){
//do some stuff
return something;
};
this.someProperty = 5;
this.j = function(){
//do some more stuff
return something;
};
}
}
But you would still need to call var a = new namespaced.A() in order to access the functions.
If you want to call namespaced.A.j() directly, you would have to declare A as object, not as function:
var namespaced = {
A: {
r: function(){
//do some stuff
return something;
},
someProperty: 5,
j: function(){
//do some more stuff
return something;
}
}
}
So it depends on what you want to achieve eventually... to get a better insight into these methods, I recommend JavaScript Patterns.
This is what you need to understand about JavaScript:
When you write
var obj = { A: a, B: b, C: c };
you are creating (and assigning to obj) an object with properties called A, B and C mapping to values a, b and c respectively. These values may very well be functions, so when you have
var obj = { A: function(){...} };
you are creating an object with a property called "A" which is a function. You can refer to it with obj.A and call with obj.A().
When you call obj.A(), the keyword this inside the body of function A will refer to obj. You can use it to assign new properties to obj:
var obj = {
A: function() { this.prop = "Hello!"; }
};
obj.A();
alert( obj.prop ); // alerts "Hello!"
So, inside namespaced.A.j() the this keyword will point to namespace.A (it's what is to the left of the last dot).
You can apply a function to an object like so: func.apply(obj) or like so: func.call(obj). In this case, the this keyword will refer to obj instead. This isn't relevant to your case, but if func takes parameters (let's say param1 and param2), you can apply the function like so: func.apply(obj, [val1, val2]) or like so: func.call(obj, val1, val2).
All variables declared inside a function live only inside that function. They are not visible outside. And when you write function doStuff(){} it's (I'm simplifying here) as good as if you wrote var doStuff = function(){}; So nested functions live and can be used only inside the surrounding function; that is, unless you assign them to something accessible from outside.
When you call something like new Cons() what happens is the creation of a new empty object followed by the application of Cons() on that object. In other words, it's the same as
var obj = {};
Cons.apply(obj);
or if you prefer:
var obj = {};
obj.Cons = Cons;
obj.Cons();
// obj's Cons property then mysteriously disappears
// unless it was explicitly set inside Cons() (oh my, how confusing! :)
So you can have this:
function Duck(name){
this.myName = name;
this.quack = function(){
alert(this.myName + " quacks!");
}
};
donald = new Duck('Donald');
donald.quack();
With all the preceding in mind, a way to write namespaced code is like this:
// The following syntax, confusing to someone who hasn't seen it before,
// is defining a new anonymous function and immediately using it
// as a constructor applied to a new empty object.
//
// Alternatively, you can use this syntax:
// var namespaced = {};
// (function(){
// ....
// }).apply(namespaced);
//
var namespaced = new (function(){
// This creates a new variable named "namespaced"
// which is visible only inside this anonymous function.
// This variable points to the still-empty object created by
// 'new'. This object will, once we're done with this anonymous function,
// be assigned to a variable, outside, which by "coincidence" is
// also named "namespaced".
var namespaced = this;
// You could alternatively not create the variable "namespaced"
// and use 'this' directly inside this anonymous function. But,
// the 'this' keyword may point to different objects inside the
// nested functions that follow, so we create it to avoid confusion.
// This assigns a new object to variable 'A', which isn't visible outside.
// Use a constructor function defined inline.
var A = new (function(){
var A = this; // 'this' now refers to the empty object created just above
this.someProperty = 5; // Two different ways of
A.anotherProperty = 7; // doing mostly the same thing
this.j = function(){
//do some more stuff
// 'this' will point to j, here
return something;
}
// Function r isn't visible outside of A's constructor like this!
function r(){
//do some stuff
return something;
}
// Make 'r' visible outside by assigning it to a property of 'A'.
// Look, it's also called "r". What fun!
A.r = r;
})();
// Make the object in variable 'A' visible outside of
// 'namespaced's constructor, by making it a property of 'namespaced'
namespaced.A = A;
// Create a new object as before.
// This time we won't make it visible outside
// of "namespaced"'s constructor.
var C = new (function(){
this.d = function (){
//do stuff we like
}
})();
// Give "namespaced" a property 'B'.
// This time it's a function instead of a nested object.
namespaced.B = function(){
// It's cool to make these function calls here, because
// (a) nested functions can see the variables ('A' & 'C')
// of surrounding functions, even if they terminate in the meantime;
// and (b) 'r' & 'd' are properties of 'A' and 'C'.
A.r();
C.d();
};
// You could return 'this' or 'namespaced' from this constructor,
// but the 'new' keyword will make sure the "namespaced" variable
// outside will get the no-longer-empty object it created,
// so you can just not return anything.
})();
// Now you can do
five = namespaced.A.someProperty;
seven = namespaced.A.anotherProperty;
something = namespaced.A.j();
namespaced.B(); // Calls A.r() and C.d()
// But you can't do
namespaced.C.d(); // WRONG: "namespaced" doesn't have a property named "C"
I hope this helps more than it confuses.

How do I determine object that function is a method of?

var A = {
x : function () { }
};
var b = function (method) {
//want to know method's "parent" here
};
b(A.x);
I want to know that x is defined in A when I call the b(A.x). Is this possible?
There's no nice built-in way to do this, because actually there are no methods in Javascript. They are independent Function objects that just happen to be assigned somewhere.
If you create new instance of function every time (e.g. closure) [thanks Matthew Crumley for pointing that out], then you can modify the function object to explicitly associate it with its parent:
x.parent = A;
and then you can call it properly as if it was a method:
x.call(x.parent);
Otherwise you will have to pass both function and its parent object.
This question makes little sense from the perspective of the language as a function may exist on many objects.
var a = { name : 'a' },
b = { name : 'b' },
c = { name : 'c' };
a.x = function () { alert( this.name ); };
c.x = b.x = a.x; // a, b, and c all reference the same function
You may call the x function with any context you want:
a.x(); // alerts "a" because "this" is object a
b.x(); // alerts "b" because "this" is object b
a.x.call( b ); // alerts "b" because "this" is object b (via parameter)
You can manipulate this behavior to work for you:
var b = function ( method ) {
// parent = this;
};
b.call( A, A.x );
There isn't however any way of knowing from inside a function what object it is assigned to as this isn't necessarily a single place.
Even adding a parent property won't work in all cases, because if the function is in the object's prototype, there is only one copy of the function object, so there's no way to tell which instance it came from. Here's an example to show the problem:
function MyClass() {
// Create a MyClass object
}
MyClass.prototype.x = function() { return 42; };
var a = new MyClass();
a.x.parent = a; // Set the parent to a
var b = new MyClass();
b.x.parent = b; // b.x and a.x both reference the same function from MyClass.prototype
Now, a.x.parent and b.x.parent are both set to b.
#porneL's method will work as long as each object gets its own copy of the function.
It's probably better to modify the function to take a parent object and a method so it will work with any function.
Every function in JavaScript is actually a Function object.
<html>
<body>
<script>
var A = {
x: function (a_a, a_b) { alert(a_a + a_b); }
};
var b = function (a_method) {
alert(a_method.toString());
a_method.call(this, 1, 2);
};
b(A.x);
</script>

Can a JavaScript object have a prototype chain, but also be a function?

function a () {
return "foo";
}
a.b = function () {
return "bar";
}
function c () { };
c.prototype = a;
var d = new c();
d.b(); // returns "bar"
d(); // throws exception, d is not a function
Is there some way for d to be a function, and yet still inherit properties from a?
Actually, it turns out that this is possible, albeit in a non-standard way.
Mozilla, Webkit, Blink/V8, Rhino and ActionScript provide a non-standard __proto__ property, which allow changing the prototype of an object after it has been created. On these platforms, the following code is possible:
function a () {
return "foo";
}
a.b = function () {
return "bar";
}
function c () {
return "hatstand";
}
c.__proto__ = a;
c(); // returns "hatstand"
c.b(); // returns "bar"; inherited from a
This might be of use to anyone who doesn't need to worry about cross-platform compatibility.
However, note that only the properties of an object can be inherited. For example:
var d = {};
d.__proto__ = a;
d.b(); // returns "bar"
d(); // throws exception -- the fact that d is inheriting from a function
// doesn't make d itself a function.
Short answer: not possible.
This line of your code:
var d = new c();
automatically assumes that d is an object. Unless c is a constructor of a builtin object, e.g., Function. But if c is already defined by the language, you cannot manipulate its prototype, and cannot "inherit" it from whatever you like. Well, in some interpreters you can, but you cannot do it safely across all interpreters — the standard says: "you doth not mess with standard objects or the interpreter will smite you!".
The builtin objects are "unique" and JavaScript does not provide ways to duplicate them. It is not possible to recreate String, Number, Function, and so on without resorting to incompatible trickery.
Based on a discussion on meta about a similar question I'm posting this answer here based on #alexander-mills original
This can now be done in a standards compliant way
First create an object which inherits Function
const obj = Object.create(Function.prototype); // Ensures availability of call, apply ext
Then add you custom methods and properties to obj
Next declare the function
const f = function(){
// Hello, World!
};
And set obj as the prototype of f
Object.setPrototypeOf(f,obj);
Demonstraction
const obj = Object.create(Function.prototype);
// Define an 'answer' method on 'obj'
obj.answer = function() {
// Call this object
this.call(); // Logs 'Hello, World'
console.log('The ultimate answer is 42');
}
const f = function() {
// Standard example
console.log('Hello, World');
};
Object.setPrototypeOf(f, obj);
// 'f' is now an object with an 'answer' method
f.answer();
// But is still a callable function
f();
Yes, it is possible if you use the __proto__ property Daniel Cassidy mentioned. The trick is to have c actually return a function that has had a attached to its prototype chain.
function a () {
return "foo";
}
a.b = function () {
return "bar";
}
function c () {
var func = function() {
return "I am a function";
};
func.__proto__ = a;
return func;
}
c.prototype = a;
var d = new c();
d.b(); // returns "bar"
d(); // returns "I am a function"
However, you'll need to do some more tweaking of the prototype chain if you want instanceof to return better results.
d instanceof c // true
d instanceof a // false
c instanceof a // false
Does it have to actually be a prototype chain? You can use a mixin pattern to make a function have all of the properties of a instead. You can even wrap it in a nice "new" syntax to fake it if you really want.
function a () {
return "foo";
}
a.b = function () {
return "bar";
}
function c () {
var f = function(){
return a();
};
//mixin all properties on a
for(var prop in a){
f[prop] = a[prop];
}
return f; //just returns the function instead of "this"
};
var d = new c(); //doesn't need the new keyword, but just for fun it still works
alert(d()); //show "foo"
alert(d.b()); //shows "bar"
You can add properties to d without affecting a. The only difference between this and what you want is that changes to a will not affect existing "instances" of c.
This is something I've been trying to do for a while now. Special thanks to the authors above for their input.
Here is a chained implementation of using a "callable-object":
var $omnifarious = (function(Schema){
var fn = function f(){
console.log('ran f!!!');
return f;
};
Schema.prototype = {
w: function(w){ console.log('w'); return this; },
x: function(x){ console.log('x'); return this; },
y: function(y){ console.log('y'); return this; }
};
fn.__proto__ = (new Schema()).__proto__;
return fn;
})(function schema(){ console.log('created new schema', this); });
console.log(
$omnifarious()().w().x().y()()()
);
Also, with this "Schema" approach, it may be possible to create a reusable interface using Object.freeze() on Schema's prototype or __proto__ object. That might look something like this: fn.__proto__ = Object.freeze(new Schema().__proto__) -- this is not a practical example and more may be needed. That said, its a different discussion. Try it out and let me know!
Hope this is helpful.

Categories

Resources