Javascript prototype - applies not only for instance objects? - javascript

Prototypes are used throughout JavaScript as a convenient means of defining
properties and functionality that will be automatically applied to instances of
objects.
So if I write this :
function Ninja(){}
Ninja.prototype.swingSword = function(){
return true;
};
var ninja1 = Ninja();
Then , All ninjas will have the method.
But if it's only for instance objects - why does the following code works ?
Object.prototype.test1=function (){alert(this);};
Object.test1();
Object is a plain object and not an instance object.
Questions:
it seems that the prototype also apply method for non-instance objects...
I couldn't find in mdn any explanation for that exact behavior .

Generally this doesn't work. Your code works, because you add function to Object prototype, and Object is function, that is instance of Function, and 'Function.prototype' is instance of Object

When you extend the prototype of Object, the property you add is available for all objects, as it's the root of all JS objects :
Object.prototype.test1 = function(){ console.log('test1') };
({}).test1(); // logs test1
(new Image()).test1(); // logs test1
And Object, like all constructors, is a function. And a function in JavaScript, is an object.

Related

Difference between Date.prototype.newFunction and Date.newFunction?

What would the difference be between Date.prototype.newFunction and Date.newFunction? I'm aware of how prototypal inheritance works in Javascript so I understand the prototype example, but the Date.newFunction throws me.
As I think you know, the prototype contains properties that will be automatically inherited by objects created via the constructor.
Date.newFunction is just a property on the constructor itself and it can only be accessed via Date.newFunction. It is not inherited by objects created via the constructor and is not accessible via a particular instance created by the constructor.
Some would say that Date.newFunction is analogous to a class static method in other languages. It's not a method attached to a particular instance, but more like a helper function for that object type. These types of methods typically do not operate on instance data and they could just as easily be global utility functions, but it is often cleaner from a namespace point-of-view to assign them as properties of the constructor.
For example, on the Javascript Date object, methods such as Date.now() and Date.parse() are examples of this type of static methods. You don't create an instance to use them, you just call them directly:
var tStart = Date.now();
One thing to remember is that any function in Javascript is an object too, so it can have arbitrary properties beyond just the .prototype property and using that capability for static methods is just one use.
Date.a = function () {
return 'Date.a';
};
Date.prototype.a = function () {
return 'Date.prototype.a';
};
Date.a(); // return 'Date.a'
var b = new Date();
b.a(); // return 'Date.prototype.a'

differences between prototype and namespace

In namespace we can use something like this:
var namespace = {};
namespace.something.nested.namespacing();
And also in prototype we can use same like name the namespace:
something.prototype.method();
In both types we are using . notation. So, how can we determine the code is using namespace or prototype?
JavaScript doesn't have namespaces. What you're calling a namespace is just an object. It's fairly common to use objects to stand in for namespaces.
Your code:
var namespace = {};
namespace.something.nested.namespacing();
...creates an object and a variable that refers to that object called namespace. Then you add properties to that object (it looks like you've added a property, something, which is also an object, which has a property, nested, which is also an object, which has a property called namespacing which refers to a function).
Your code:
something.prototype.method();
...is also using an object. The above would actually be a really unusual thing to do, you're calling a function (method) by directly referring to the prototype property of what I assume is a function (something). That's not normally what you would do. Normally you'd create an object via the function:
var s = new something();
...and then use the prototype that got assigned to s implicitly:
s.method();
The prototype property on functions can be confusing to people new to JavaScript. It's just a normal property like any other property, which is on function instances. The only thing that makes it special is the new operator: When you call a function via new:
var s = new something();
...the JavaScript engine creates a new, blank, object, then sets its underlying prototype (sometimes called __proto__ but that's not in the spec [yet]) using something.prototype, like this:
// pseudo-code for `var s = new something()`
var tmp = {}; // New, blank object
tmp.__proto__ = something.prototype; // Assign a prototype to the new object
something.call(tmp); // Call `something` with `this` referring to `tmp`
s = tmp; // Assign the result to `s`
(There's a detail I left out in the above to avoid confusing matters, to do with the special case where something has an explicit return statement in it that returns an object reference.)
Well, namespaces are just objects and prototype objects are objects, so from a syntactic point of view, there is no difference how you access them (foo.bar is called dot notation().
However, they serve two fundamentally different purposes:
Namespaces are used to structure your code and to avoid global namespace pollution.
Prototypes are used to share methods between multiple instances of the same constructor function.
So you usually don't call a method directly on the prototype because it most likely won't work. The purpose of this method is to be called on an instance of the corresponding constructor function. For example:
function Something() {}
Something.prototype.foo = function() {};
var s = new Something();
s.foo();
The . notation is a very general purpose tool used in javascript for accessing any properties of any object.
var x = {};
x.val = 2;
Your reference to a namespace is just a general purpose object in javascript as there is no actual namespace type in javascript. In other words, plain objects are used to create namespace-like things in javascript. So, as such, object properties are used to keep track of names in the namespace.
The . notation's use with the prototype is one specific instance of accessing properties on a specific type of object (the prototype). A prototype is used on a function object and has a very specific use when creating new instances of that function.
function foo() {
}
foo.prototype.talk = function() {
alert("hello");
}
var y = new foo();
y.talk();

Object literal as prototype

This question is more about support and backwards compatibility. I have tested the following code.
function newFunc() {}
newFunc.prototype = {
literal : {
init : function() {
console.log(this);
this.test();
},
test : function() {
console.log('test');
}
}
}
var inst = new newFunc();
inst.literal.init();
This works, though I've not seen object literals as prototypes in any other code. Is there a reason for this? This seems like a logical way of coding to me though I don't want to pursue it if it has serious pitfalls.
It's perfectly normal to use an object literal to create the prototype for a function, but normally only as the actual value of the prototype object.
What's unusual is doing what you've done and include a nested object within the prototype.
In effect you've only added one object to the prototype, the one named literal. All of the methods are then properties of that object. It's technically valid syntax, but I've never seen it used before. As #squint points out in the comments, it also appears to break the way that the this variable works, because it binds this to the "next left" property that was used in the function call:
var inst = new newFunc();
inst.literal.init();
> Object { init: function, test: function }
i.e. this has been set to point at the .literal object, and not at the actual instance that has been created.
Yes, using literals for prototype is correct. For example Mozilla explicitly uses a literal in the prototype's documentation:
var Customer = function(name) {
this.name = name;
}
var Person = { // this is a literal
canTalk : true,
greet : function() { /* ... */ }
}
Customer.prototype = Person;
Some explanation: Value of prototype is an object. It doesn't matter how the object was created - using simply {} is fine. It is often initialized using something like MyClass1.prototype = new MyClass2(), but new just creates a new object. It also sets the prototype property and executes the constructor (MyClass2) but on the new object, it doesn't affect MyClass1 in any way (see explanation here).
Using a nested literal doesn't make a difference. In the question, the prototype is set to { literal : { ... } }. What actually happens when you call inst.literal.init() is:
The runtime looks at inst and checks whether the object has a value assigned for property literal.
inst dos not have such property, therefore the runtime continues with its prototype property
inst.prototype references the literal object to which it was initialized. This object has assigned a value for property literal.
inst.literal therefore evaluates to the nested literal inst.prototype.literal
The literal object does have a value for property init
The init() function is called
This is one of the principles of JavaScript (ECMA Script) so there should be no compatibility issues.
What you are doing is setting the prototype to be a JavaScript object with several properties. This is perfectly acceptable, as functions act very similarly to objects in JavaScript. All JavaScript does is passes the reference to this prototype property down to inherited objects, so they will not have a function they can access, but an object instead in this case.
You can see that this is actually done in the MDN documentation:
var Person = {
canTalk : true,
greet : function() {
if (this.canTalk) {
console.log("Hi, I'm "+this.name)
}
}
}
Customer.prototype = Person;
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype?redirectlocale=en-US&redirectslug=JavaScript%2FReference%2FGlobal_Objects%2FObject%2Fprototype
if i understand it right they say you can do that in javascript (ECMA SCRIPT)
http://en.wikipedia.org/wiki/Literal_(computer_programming)
but what i know is that if you want to instance your Object there is an issue for old browsers..that you cannot instance objects with the Object.create() function
so you should generally do like this...
var foo = function(){};
foo.prototype = {func:function(){}}
var bar = new foo();
like you do so or so :)

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 does an object reference itself in 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.

Categories

Resources