How does an object reference itself in Javascript? - javascript

I was experimenting with inheritance in javascript, and wrote those two functions:
Object.prototype.inherits=function(obj){this.prototype=new obj;}
Object.prototype.pass=function(obj){obj.prototype=new this;}
This code works very well:
Dog.inherits(Animal);
But the following fails:
Animal.pass(Dog);
As I understand it, my pass functions doesn't work, because "this" isn't a reference to the object instance itself? If that's the case, how can I reference the object from within itself?
Thanks in advance!

Well, actually the two are doing exactly the same:
Dog.prototype = new Animal;
The this value inside the methods will refer to the base object where the reference was invoked, in the case of:
Dog.inherits(Animal);
The this value will refer to the Dog constructor function, and the obj argument will be the Animal function.
When you call:
Animal.pass(Dog);
The this value will refer to the Animal function, doing at the end exactly the same thing as the inherits method, but the other way around.
I would recommend you to not extend the Object.prototype object, because it can cause you a lot of problems, for example those two properties will be enumerated in any for-in loop, e.g.:
for (var prop in {}) { // <-- an empty object!
alert(prop); // will alert 'inherits' and 'pass'
}
All objects inherit from Object.prototype, and it seems that you intend to use those methods only on Function objects, it would be safer to extend the Function.prototype object, or implement the methods as functions that take two parameters.

Works for me, with test code like:
function Animal() {}
Animal.prototype.isanimal= 1;
function Dog() {}
Animal.pass(Dog);
Dog.prototype.isdog= 2;
alert(new Dog().isanimal); // 1
alert(new Dog().isdog); // 2
However, bear in mind that new this or new obj will call the function this/obj, creating a new full instance. If you have constructor code in that function that expects to receive some arguments, or sets up instance state, you can end up with problems. To create a new this without calling this as a function you can use a different constructor that does nothing:
function nonconstructor() {}
nonconstructor.prototype= this.prototype;
obj.prototype= new nonconstructor();
Also, you should avoid prototyping onto Object. This will cause trouble for code using Object as a general-purpose lookup map. As you only seem to be working with constructor-functions, prototyping onto Function should meet your needs and is much safer.

Related

Javascript : Difference between Function and Function. Prototype

If we create a function like:
function Rabbit() {}
We see that it inherits from the same object that Function inherits from i.e.
Rabbit.__proto__ === Function.__proto__
What is this higher object? If we try to log it it looks like : ƒ () { [native code] }. Shouldn't Rabbit be inheriting from Function object because it's a function? Can somebody explain where i'm wrong?
What is this higher object?
It's the object referenced by Function.prototype, which is also a function. It's where functions get their properties and methods from (call, apply, bind, name, and length).
That object's prototype is the object referenced by Object.prototype, which is responsible for basic object properties and methods such as hasOwnProperty and toString and, since you used it in your example, __proto__ (which is a web-only feature for backward compatibility; don't use it, use Object.getPrototypeOf instead).
Shouldn't Rabbit be inheriting from Function object because it's a function?
No, that's what Function.prototype is for.
Let's put Function, specifically, aside for a moment. Suppose you have:
function Thingy() {
}
and
let t = new Thingy();
Object.getPrototypeof(t) === Thingy.prototype will be true, because when you use new Thingy, the resulting object gets the object that Thingy.prototype points to as its prototype. This is how constructor functions and prototypes work in JavaScript.
Function is a constructor that creates functions. So the equivalent would be:
let Rabbit = new Function();
Object.getPrototypeOf(Rabbit) === Function.prototype is true. It's also true for functions that, like your Rabbit, aren't created via new Function.
Shouldn't Rabbit be inheriting from Function object because it's a function?
No, because it is a regular function. Every function you create this way is actually a Function object instance. See mdn.
In order to make a Function be a prototype of your object you need to explicitly specify it as a prototype of your object and create an instance using new keyword.

JavaScript prototype vs. this in practice

I've read many questions with valid and understandable answers here in Stack Overflow and other sites over the web, and I think I understand everything I need for using JavaScript to make object-oriented apps, save one thing: What is the real, practical purpose of using a class' prototype over this?
I've read that any method, even one set as a this member, will be called from the constructor (class) function, and not re-created for each instance.
I've seen many examples of using prototype for setting methods, implying that it would save memory by using the original class-function's method on the instance, and not a brand new attribute.
So, along with remarking which of the two options above is true, I'd like to know: is a prototype method accessing the constructor's this ("public") variables or the instance's (which may have been set as different from the constructor's)?
Edit - is using this.prototype.method = function() inside the constructor's scope wrong? All examples I've seen set a prototype method after the function has been created.
I'll try to answer your question regarding the relationship between the prototype method and this by example.
From the moz docs:
If the method is on an object's prototype chain, this refers to the
object the method was called on, as if the method was on the object.
Example:
// Our constructor function
function Example() {
this.publicGreet = "Hello World";
};
// Here the function is set as a property of the constructors prototype
Example.prototype.greet = function() {
alert(this.publicGreet);
};
// This creates a new object and invokes the constructor function
// Sets publicGreet as a property of that object and assigns it the value "Hello World"
var exampleInstance = new Example();
// Looks up the prototype chain and invokes it as a method of exampleInstance
// Remember our definition of `this` for methods on the prototype chain?
// Hence, `this` refers to exampleInstance, therefore `this.publicGreet` is "Hello World"
exampleInstance.greet();
This test should explain the performance problem: http://jsperf.com/prototype-vs-instance-functions/6
But yes, prototype saves memory because one callback is defined and instances simply points to this callback. There's no need to declare bunch of copies of the same callback.
Access issue: "this" declared within function inside this.prototype refers to "this" of instance: http://jsfiddle.net/pHtjK/
var b = Function;
b.prototype.a = function(){alert(this.b);};
var xyz = new b();
b.b = 'what';
b.a();

understanding simple class emulator in JavaScript

Recently I started to learn a bit more advanced JavaScript (as far I only used jQuery for some simple tasks) and bought a book of Alex MaxCaw "JavaScript Web Applications". The first chapter treats about creating simple class emulator. I understand almost everything except for two lines of code marked with comments down below:
var Class = function(parent) {
var _class = function() {
this.init.apply(this, arguments);
};
if(parent) {
var subclass = function() {};
subclass.prototype = parent.prototype;
_class.prototype = new subclass();
};
_class.prototype.init = function() {};
_class.fn = _class.prototype;
//????
_class.fn.parent = _class;
//????
_class._super = _class.__proto__;
return _class;
};
Can anyone tell me what is purpose of these two lines? I'll be very thankfull.
Walking through the code:
Class is defined as a function that calls init with the arguments provided it. This means you can call it with standard constructor syntax using new eg. var instance = new Thingy() and get the init function called with the proper this value.
If you pass a parent class in, your class gets that class's prototype property added to the prototype chain of a new empty object which it uses as its prototype property. A more succinct way of doing this in modern browsers is _class.prototype = Object.create(parent.prototype);
The init function is defined. This should likely be overridden with more useful initialization code after a _class instance is created (or the code should be changed to allow the passing in of an init function when you create a Class... or allow the instance to walk the prototype chain to look for other init functions.
_class.fn is created to provide a reference to the _class constructor's prototype function.
_class.fn.parent is created to provide a reference back to the constructor. This may be useful if you are applying the prototype in some other context and want a reference back to the prototype's constructor.
_class._super is assigned the internal, non-standard __proto__ property of the constructor. Remember that constructors are functions and, in Javascript, functions are objects. This means they have their own internal prototypes. The earlier references to prototype are the prototype assigned to objects created with this constructor NOT the constructor's prototype itself. All functions inherit from Function.prototype, which is where they get bind, apply, etc. _super in this case is just a reference to Function.prototype.
As to when this type of _super is used, one could imagine doing the following:
function Maker(){ //this will be called as a constructor, ie. with new
var fun = function(){}; //Make a function
fun.__proto__ = this.__proto__; //yuck. Set the function's this value to the instance
return fun; //return the function
}
Maker.prototype={say:function(){console.log("Javascript is fun!.. And weird.")}};
var fun = new Maker();
fun.say() //"Javascript is fun!.. And weird."
console.log(fun.__proto__) // Object{say:function}
console.log(fun.bind) // undefined!!
Woah! What just happened?
In fact, you replaced your functions internal prototype with an Object. This allows you to build up interesting prototype chains and interact with both functions and objects in a similar way. Note, however, that the link with Function.prototype has been severed, which is why we don't have access to bind. However let's fix it with more prototype magic!
function FunctionConnector(obj){
for (var prop in obj){
if(obj.hasOwnProperty(prop){
this.prop=obj.prop
}
}
}
FunctionConnector.prototype=Function.prototype;
Maker.prototype=new FunctionConnector({say:function(){
console.log("Javascript is fun!.. And weird.")
}});
var fun = new Maker();
fun.say() //"Javascript is fun!.. And weird."
console.log(fun.__proto__) // Object{say:function}
console.log(fun.bind) // function bind(){ [native code] }
Now what is that FunctionConnector? It takes an object and, when called as a constructor, returns an object that both has all the properties of the passed object AND inherits from Function.prototype. As you can see, our access to bind has returned (Of course we also could have made do with our original implementation and just Function.prototype.bind.called our way to victory).
With this new pattern in hand it may be clearer what _super in your code does, namely it references the built in prototype of the _class constructor you are making (In our example the instance of FunctionConnector would be _super). This reference could be used to patch the prototype at runtime, call methods with apply or anything else you can due with a reference to an object.
This is, as you may have noticed a little hackish, especially since __proto__ is nonstandard. But it's also somewhat neat if you enjoy the patterns it allows. I'd recommend only doing something like this if you are very confident in your knowledge of Javascript inheritance, and perhaps not even then unless you are in charge of your entire code base.
From what i know, fn is just an alias to the prototype property
And about the _super, that one is for referencing to the "class" from which you are inheriting
Here's more about the use of _super and js inheritance: article

If there is no distinction between classes and objects why doesn't this code work?

I was always taught that in Javascript there is no distinction between objects and classes. Then can someone explain why this code generate error:
var firstObj = function() {};
firstObj.prototype.sayHi = function() {
document.write("Hi!");
};
firstObj.sayHi();
Whereas this one works:
var firstObj = function() {};
firstObj.prototype.sayHi = function() {
document.write("Hi!");
};
new firstObj().sayHi();
What's the difference? Why isn't the first one working?
The key issue here is that your firstObj variable is a Function object, not a firstObj object. This is a subtle distinction, but the type of object determines which prototype it inherits.
The prototype is like a template that is applied to newly created objects of a particular type. You must create a firstObj object (usually with new which invokes the constructor and assigns a prototype) in order to have that template applied to it. In the first example, your firstObj variable is a Function object, not a firstObj object so it has the prototype of a Function not of anything else..
In your second example, you actually create a firstObj object so it inherits the prototype for that type of object.
If you want the method applied in your first example so it works on the function object you've already created, just put the method directly on your already existing function object, not on the prototype.
There is no difference in the language between objects and classes1. However, there is a big difference between one kind of object and another. In the first case:
firstObj.sayHi();
you are trying to access the sayHi property of firstObj, which is a Function object that does not have such a property. (You could, however, do firstObj.prototype.sayHi().)
In the second case:
new firstObj().sayHi();
you are first invoking the new operator on the firstObj object, which evaluates to a new object. That new object has firstObj as it's constructor property and a prototype equal to the prototype property of firstObj. You are then accessing the sayHi property of that returned object, which succeeds because sayHi is in the prototype chain for that object.
1 Technically, JavaScript doesn't have classes2 (in the traditional sense), just constructor functions that are usually called "classes".
2 However, class is a future reserved word.
when you write this:
var firstObj = function() {};
you only define a constructor function, thus you need to use the key word new for the new objects created with this constructor function.
A function is just a function until new is issued. At that point, a Function Object is created based on the prototype for the function. That is why you will not see the sayHi method present in the first version.
Also, firstObj is a function, and not an object, so you need to invoke it to actually have anything happen. firstObj will not actually invoke the function, you must use firstObj().
Further, there are ways to have the prototype used without explicitly requiring the new keyword. This is done in a number of popular frameworks (such as jQuery). It is done by checking to see if new was used, and if it was not, then it news one up for you on the spot:
jsFiddle Demo
var firstObj = function() {
if( !(this instanceof firstObj) ){
return new firstObj();
}
};
firstObj.prototype.sayHi = function() {
alert("hi");
};
firstObj().sayHi();

How is this possible without instantiating (new-'ing') it: var a = Array.prototype.slice.call(arguments)?

In the context of inside a function, here's the code (based on the standard pattern of making a function's 'arguments' into an array):
var args = Array.prototype.slice.call(arguments);
I'm trying to study this out (am a beginner at JavaScript, coming from C#).
I understand that slice is an instance method due to it being a prototype function of Array.
I also understand that this is not a static 'utility function', meaning to use it, you have to new it up like so: (example) var myArray = new Array(); myArray.slice(...);
call passes an object in here to change the context to that of arguments
Related to this, I don't also know the difference between
Array.prototype.slice.call([32,32,121,412]) and Array.prototype.slice([32,32,121,412]) not in the context of call.
So, here's my question:
I just don't get how this works in relation to instance vs static methods... so can anyone explain the intricacies of var args = Array.prototype.slice.call(arguments);?
Why can this be used without calling new?
Why was this possible? It's not a Static method, and it must be 'newed' up, and it only works when you use call function... (at least in my C# mentality...)
The difference between Array.prototype.slice.call([32, 32, 121, 412]) and Array.prototype.slice([32, 32, 121, 412]) is that in the first case, the actual Array [32, 32, 121, 412] becomes the "this" object for the call. In other words, it's just like this code: [32, 32, 121, 412].slice(). Just calling slice on the prototype executes it in the context of the prototype object, which probably wouldn't do anything useful.
When you add a function to an object's prototype, it becomes a function that you can use on instances of that object. The context of that function with be the instance. i.e.
Array.prototype.myFunction = function() {
alert( this[0] ); // this should refer to the Array instance
};
var x = new Array(1);
x[0] = 5;
x.myFunction(); // alerts 5
However, sometimes you may have a structure like an array that are not a subclass or instance of Array (such as an Arguments object). What the call method of a function does is changes the context to whatever the first parameter to call is. In this case, the call method is being called on a function of the Array's prototype. In all reality, Array.prototype.myFunction is just a function defined in the above block of code. call is a method that can be called on any function to change its context. Therefore, instead of an Array instance as the context, you would have an arguments object.
function foo() {
Array.prototype.myFunction.call( arguments ); // arguments is [6]
// alerts 6
}
foo( 6 );
More info on call.
I think perhaps you're getting confused by the behaviour of "instance" and "static" methods in languages like Java that have classes. JavaScript doesn't work the same way.
Also you're confused about another issue, that being how all JS function calls work in terms of setting this within the called function (i.e., setting what object the function will likely attempt to operate on) and what effect .call() has on setting this.
The .slice() method is defined as a property of Array.prototype, not as a Java-style "instance method" on the individual array instances. You can call Array.prototype.slice() without needing an instance of an array created with new.
When you say:
myArray.slice()
JS will first see if .slice() actually is a method of the myArray object, and then (given that it isn't) it will see if it is a method of the Array prototype - which it is, so it runs that method.
When you call any JS function with "dot" notation, i.e., myArray.slice(), within that function the special variable this will be set to the object. this is a reference to the object that the function should operate on. But if you call a JS function using .call(), within that function this will be set to the object you pass as a parameter to .call(). So
myArray.slice()
says to call .slice() and have it operate on myArray.
var args = Array.prototype.slice.call(arguments);
Says to call .slice() and have it operate on arguments
P.S. don't use var myArray = new Array(); - better to say var myArray = [];
Unlike C#/Java, functions are actually first-class citizens in JavaScript.
In a general sense:
This means there is no need to "new" it up.. it works exactly as it is because it is its own object.
"new"ing up a function (in a general sense) merely changes the 'this' value of that function to the variable it will be assigned to, then returns it.
It is possible to use a function in JavaScript without "newing" it up because they are "first-class citizens" in JavaScript.
In a more in-depth sense, this is what "new" does:
- it creates a new object deriving from MyConstructor.prototype
- it assigns the 'this' value of the constructor function to the new object
- execute the code inside (adds properties to new object/instance)
- returns the new object
Some extra notes about what I learned from instances:
- they don't have a .prototype property like their constructor functions
- though they have a [[prototype]] property, derived from MyConstructor.prototype
- overriding a property in the instance shadows the MyConstructor.prototype[property]..

Categories

Resources