I have an issue when I want to add a method to Object class in JavaScript. I don't know the different between Object.myMethod and Object.prototype.myMethod.
Object.myMethod = function (){};
Object.prototype.myMethod = function (){};
Can anyone help me out
Object is the constructor function. Like all functions in JavaScript, it is an object, and you can attach properties to it. Those properties can be functions. So doing
Object.myMethod = function () { };
attaches myMethod to the Object constructor function, which means you can call it like so:
Object.myMethod();
Object.prototype is the prototype used as a base for all JavaScript objects. It is itself an object, and so again you can attach properties to it. The difference is, properties attached to the prototype get prototypally-inherited by all objects via their internal [[Prototype]] reference, so something like this is possible:
Object.prototype.myMethod = function () { };
var obj = {};
obj.myMethod();
var otherObj = { something: "else" };
otherObj.myMethod();
var objectViaConstructor = new Object();
objectViaConstructor.myMethod();
var instanceOfSomethingThatInheritsFromObject = new XMLHttpRequest();
instanceOfSomethingThatInheritsFromObject.myMethod();
Note that most of the above applies for arbitrary constructor functions, with the exception that you do not get a special object literal syntax, and Object is special in that everything (up to and including the example XMLHttpRequest) inherits from it. So:
function MyConstructor() { }
MyConstructor.staticMethod = function () { };
MyConstructor.prototype.method = function () { };
MyConstructor.staticMethod();
var myConstructed = new MyConstructor();
myConstructed.method();
Object.myMethod is a method on a single object, it's similar to a Static Method in languages with classical OOP.
Object.prototype.myMethod is a method that will exist on all instances of an object, similar to an Instance Method (sometimes just called a Method, vs a Static Method) in languages with classical OOP.
If you're creating instances of your Object (i.e. new MyClass()) then use a prototype method.
Related
What the different if both of them call the constructor "Array" and generate an object?
I know that we lost this if we create some object without new:
function Animal(name) {this.name = name}
var duck = Animal('duck'); // undefined
But how that works for new Array(n) and Array(n)?
There is no difference. Check this article:
You never need to use new Object() in JavaScript. Use the object
literal {} instead. Similarly, don’t use new Array(), use the array
literal [] instead. Arrays in JavaScript work nothing like the arrays
in Java, and use of the Java-like syntax will confuse you.
Do not use new Number, new String, or new Boolean. These forms produce
unnecessary object wrappers. Just use simple literals instead.
...............................
So the rule is simple: The only time we should use the new operator is
to invoke a pseudoclassical Constructor function. When calling a
Constructor function, the use of new is mandatory.
Such behaviour for Array is described in spec.
You can achive the same behaviour like this
function Animal(name) {
if(!(this instanceof Animal)) {
return new Animal(name);
}
this.name = name
}
var duck = Animal('duck'); //Animal {name: "duck"}
But a better idea would be to follow a simple code style convention that all functions starting with a captial letter are constructors and should be called with new. And set up a linter you prefer to check your code follows this rule.
JavaScript uses prototypal inheritance . When you use new command, It inherits from Object . Incase you want to inherit from an user defined object (e.g. Animal) you need to use new Animal() or without using new you can do it in following way.
// Function object acts as a combination of a prototype
// to use for the new object and a constructor function to invoke:
function Animal(name){
this.name = name
}
var inheritFrom = function(parent, prop){
// This is how you create object as a prototype of another object
// var x = {} syntax can’t do this as it always set the newly
//created object’s prototype to Object.prototype.
var obj = Object.create(parent.prototype);
// apply() method calls a function with a given this value
//and arguments provided as an array
parent.apply(obj, [prop]);
return obj
}
var duck = inheritFrom(Animal, 'duck');
console.log(duck.name); // ‘duck’
Having this:
sillyObject = {
init: function init(sillySettings) {
name = sillySettings.name
}
};
sillyObject.showAlert = function(x) {
return alert(x);
};
When I run this code:
var sillyvar = new sillyObject()
sillyvar.init(mySettings);
silly.showAlert("silly!");
I get an error but instead if I run the same thing using Object.create it runs..
var sillyvar = Object.create(sillyObject);
sillyvar.init(mySettings);
silly.showAlert("silly!");
Any (silly) help will be appreciated.
new and Object.create are two fundamentally different things.
new is going to expect to be followed by a function, and if not (as you saw) it will give you an error. That is because new expects to call a constructor function and then use that as a basis for a new execution context. During that context, the function has this bound to the scope of the execution context. Once the function is done executing it returns the this value which usually has had some data attached to it. In your example, that would look like this:
function sillyObject() {}
sillyObject.prototype.init = function(sillySettings) {
//perhaps you wanted to attach this name to the sillyObject?
name = sillySettings.name;
//which would look like this
this.name = sillySettings.name;
//because `this` here refers to the object context (remember?)
};
sillyObject.prototype.showAlert = function(x){
return alert(x);//returning alert simply returns undefined (not sure why this is used here)
};
and then you could use new, it would create the execution context using the constructor and then attach the prototype and you would end up with a new instance of sillyObject (all instances would be different).
var sO = new sillyObject();
sO.init(mySettings);
sO.showAlert("silly!");
Object.create() on the other hand is expecting an object as an argument (which is why your version worked here). It will create a new object using that object argument as a template basically. Or as MDN explains it "The Object.create() method creates a new object with the specified prototype object and properties". This basically creates a copy if nothing else is done with the Object, and that is why the alert worked here but not in the new version.
If you tried doing new sillyObject(), the error you get is Uncaught TypeError: object is not a function since sillyObject is an object and not a function.
This answer gives a good overview on the new keyword.
Object.create does not do the same thing as new. It will create a new object with sillyObject as the prototype.
sillyObject is a Object not a function. new will create a new instance of a function. You probably want to use this or just .prototype
var sillyObject = function () {
this.sillySettings = {};
}
sillyObject.prototype = {
init : function (name) {
this.sillySettings.name = name;
},
showAlert: function (x) {
return alert(x);
}
};
var silly = new sillyObject();
silly.init('foo');
silly.showAlert('bar');
this.sillySettings isn't a function so we don't keep it in the prototype. We can keep init and showAlert in the prototype. We use prototype because when using new we use sillyObject() so imagine the variable silly being replaced this sillyObject() showing why we use prototype because silly is instantiated as a function.
I have noticed I can create the same object using a constructor in two different ways.
var myObj = Object()
var myObj = new Object()
I can add properties to both using these methods. myObj.age = 1 and myObj['age'] = 1. The properties of both can be accesed the same way.
So what is the actual difference between these two ways I created myObj? Also is one of these the better way to create an object?
The difference is that the first one simply calls Object() as a function, within the scope of the window object.
The second one actually instantiates a new object. It's the one you want to use to create an object.
The difference may not be obvious with the Object() function, but let's say you create your own type, like so:
function User(name) {
this.name = name;
}
var u1 = User("John");
var u2 = new User("Jane");
console.log(u1); // *undefined* because `User()` doesn't return anything.
console.log(this.name); // John
console.log(window.name); // John
console.log(u2.name); // "Jane"
The Object function itself is a special case--it does create a new Object. But since most functions don't work that way, it's good to get in the habit of using the new keyword when instantiating things. If you're just creating a plain old Object, on the other hand, most people prefer the more concise syntax:
var myObj = {};
The first statement is a function call, meaning that myObj will get whatever is returned in the Object() function. As it happens, the function Object() will provide you with a reference to an Object object, whereas 'normal' constructors will not.
See f.e. the following:
function O(){
this.bla= "bla";
return this;
}
Calling O() here will yield a reference to window, not to an instance of O.
I come from a Java background, completely understand what constructor does in java. I am new to javascript and trying to understand why a constructor is called constructor function. Do constructors and constructor functions mean different things in javascript ?
A constructor in JavaScript is a function that is used to construct an object. For example:
function Obj() {
// The constructed object is bound to the 'this' variable
this.property = "someValue";
}
var obj = new Obj();
console.log(obj.property); // Will print "someValue"
console.log(obj.constructor); // Will print Obj's code
Obj is now the constructor of the instance obj. Obj is just a normal function, but since it's invoked via new it acts as a constructor.
Note that constructor functions are by convention named like Java classes, i.e. Upper CamelCase. The language doesn't enforce it in any way, but it makes it clear that a function is intended as a constructor.
You can also achieve inheritance in JavaScript, even though the language lacks classes per se, by defining constructors' "prototypes":
// Base constructor, like a baseclass in Java
function Base() {
this.baseProperty = "baseValue";
}
// Base implementation of a method
Base.prototype.printSelf = function () {
console.log(this.baseProperty);
};
// Constructor, corresponding to a subclass in Java
function Obj() {
// Call "baseclass" constructor
Base.call(this);
this.property = "someValue";
}
// Inherit prototype from Base
Obj.prototype = Object.create(Base.prototype);
// Overload printSelf
Obj.prototype.printSelf = function () {
// Call base implementation
Base.prototype.printSelf.call(this);
console.log(this.property);
};
var obj = new Obj();
obj.printSelf();
See my fiddle for a live demonstration if you like.
Java constructors are special functions that can only be called at object creation; JavaScript "constructors" are just standard functions.
JS has no special handling or type called function constructor. It's a term used to imply that this function is used with the new keyword to create an object. Any function can be a "function constructor" by prefixing it with the new keyword.
Of course that is usually not the intention of the author. So the convention is to uppercase the first letter of the function name to denote that is a function constructor and should therefore be used in conjuction w/ new.
The term constructor is usually meant to mean function constructor. Most in the community use the term full term since JS has no classes, and function constructor is more clear.
I am just learning Javascript and I was wondering, is using the prototype declaration, like this:
function TSomeObj()
{
this.name="my object";
}
TSomeObj.prototype.showname = function() {
alert(this.name);
}
Basically the same as doing it like this:
function TSomeObj()
{
this.name="my object";
this.showname = function() {
alert(this.name);
}
}
When I dump the object's properties I get the same result:
TSomeObj (inline version) =
{
'name': 'my object',
'test': function
}
TSomeObj (prototype declaration) =
{
'name': 'my object',
'test': function
}
What exactly is the benefit of using prototype declarations? Except less cluttering and more orderly sourcecode perhaps.
Update: I should perhaps have made it more clear that it was the final result i was curious about. The end result is ofcourse the same (i.e both register a new function in the object prototype) - but the way they do it is wildly different. Thank you for all replies and info!
Note: This answer is accurate but does not fully reflect the new way to create classes in JavaScript using the ES6 class Thing {} syntax. Everything here does in fact apply to ES6 classes, but might take some translation.
I initially answered the wrong question. Here is the answer to your actually-asked question. I'll leave my other notes in just in case they're helpful to someone.
Adding properties to an object in the constructor function through this.prop is different from doing so outside through Object.prototype.prop.
The most important difference is that when you add a property to the prototype of a function and instantiate a new object from it, that property is accessed in the new object by stepping up the inheritance chain rather than it being directly on the object.
var baseobj = {};
function ObjType1() {
this.prop = 2;
}
function ObjType2() {}
ObjType1.prototype = baseobj;
ObjType2.prototype = baseobj; // these now have the *same* prototype object.
ObjType1.prototype.prop = 1;
// identical to `baseobj.prop = 1` -- we're modifying the prototype
var a = new ObjType1(),
b = new ObjType2();
//a.hasOwnProperty('prop') : true
//b.hasOwnProperty('prop') : false -- it has no local property "prop"
//a: { prop = 2 }, b : { prop = 1 } -- b's "prop" comes from the inheritance chain
baseobj.prop = 3;
//b's value changed because we changed the prototype
//a: { prop = 2 }, b : { prop = 3 }
delete a.prop;
//a is now reflecting the prototype's "prop" instead of its own:
//a: { prop = 3 }, b : { prop = 3 }
A second difference is that adding properties to a prototype occurs once when that code executes, but adding properties to the object inside the constructor occurs each time a new object is created. This means using the prototype performs better and uses less memory, because no new storage is required until you set that same property on the leaf/proximate object.
Another difference is that internally-added functions have access to private variables and functions (those declared in the constructor with var, const, or let), and prototype-based or externally-added functions do not, simply because they have the wrong scope:
function Obj(initialx, initialy) {
var x = initialx,
y = initialy;
this.getX = function() {
return x;
}
var twoX = function() { // mostly identical to `function twoX() { ... }`
return x * 2;
}
this.getTwoX = function() {
return twoX();
}
}
Obj.prototype.getY = function() {
return y; // fails, even if you try `this.y`
}
Obj.prototype.twoY = function() {
return y * 2; // fails
}
Obj.prototype.getTwoY = function() {
return twoY(); // fails
}
var obj = new Obj();
// obj.y : fails, you can't access "y", it is internal
// obj.twoX() : fails, you can't access "twoX", it is internal
// obj.getTwoX() : works, it is "public" but has access to the twoX function
General notes about JavaScript objects, functions, and inheritance
All non-string and non-scalar variables in JavaScript are objects. (And some primitive types undergo boxing when a method is used on them such as true.toString() or 1.2.valueOf()). They all act somewhat like a hash/dictionary in that they have an unlimited(?) number of key/value pairs that can be assigned to them. The current list of primitives in JavaScript is: string, number, bigint, boolean, undefined, symbol, null.
Each object has an inheritance chain of "prototypes" that go all the way up to the base object. When you access a property of an object, if that property doesn't exist on the object itself, then the secret prototype of that object is checked, and if not present then that object's prototype, so on and so forth all the way up. Some browsers expose this prototype through the property __proto__. The more modern way to get the prototype of an object is Object.getPrototypeOf(obj). Regular objects don't have a prototype property because this property is for functions, to store the object that will be the prototype of any new objects created using that function as their constructor.
A JavaScript function is a special case of an object, that in addition to having the key/value pairs of an object also has parameters and a series of statements that are executed in order.
Every time a function object is invoked it is paired with another object that is accessed from within the function by the keyword this. Usually, the this object is the one that the function is a property of. For example, ''.replace() boxes the string literal to a String, then inside the replace function, this refers to that object. another example is when a function is attached to a DOM element (perhaps an onclick function on a button), then this refers to the DOM element. You can manually choose the paired this object dynamically using apply or call.
When a JavaScript function is invoked with the new keyword as in var obj = new Obj(), this causes a special thing to happen. If you don't specifically return anything, then instead of obj now containing the return value of the Obj function, it contains the this object that was paired with the function at invocation time, which will be a new empty object with the first parent in its inheritance chain set to Obj.prototype. The invoked Obj() function, while running, can modify the properties of the new object. Then that object is returned.
You don't have to worry much about the keyword constructor, just suffice it to say that obj.constructor points to the Obj function (so you can find the thing that created it), but you'll probably not need to use this for most things.
Back to your question. To understand the difference between modifying the properties of an object from within the constructor and modifying its prototype, try this:
var baseobj = {prop1: 'x'};
function TSomeObj() {
this.prop2 = 'y';
};
TSomeObj.prototype = baseobj;
var a = new TSomeObj();
//now dump the properties of `a`
a.prop1 = 'z';
baseobj.prop1 = 'w';
baseobj.prop2 = 'q';
//dump properties of `a` again
delete a.prop1;
//dump properties of `a` again
You'll see that setting a.prop1 is actually creating a new property of the proximate object, but it doesn't overwrite the base object's prop1. When you remove prop1 from a then you get the inherited prop1 that we changed. Also, even though we added prop2 after a was created, a still has that property. This is because javascript uses prototype inheritance rather than classic inheritance. When you modify the prototype of TSomeObj you also modify all its previously-instantiated objects because they are actively inheriting from it.
When you instantiate a class in any programing language, the new object takes on the properties of its "constructor" class (which we usually think of as synonymous with the object). And in most programming languages, you can't change the properties or methods of the class or the instantiated object, except by stopping your program and changing the class declaration.
Javascript, though, lets you modify the properties of objects and "classes" at run-time, and all instantiated objects of that type class are also modified unless they have their own properties that override the modification. Objects can beget objects which can beget objects, so this works in a chain all the way up to the base Object class. I put "classes" in quotes because there really isn't such a thing as a class in JavaScript (even in ES6, it's mostly syntactic sugar), except that the new keyword lets you make new objects with the inheritance chain hooked up for you, so we call them classes even though they're just the result of constructor functions being called with the new keyword.
Some other notes: functions have a Function constructor, objects have an Object constructor. The prototype of the Function constructor is (surprise, surprise) Object.
Inheriting from an object without the constructor function running
In some cases, it's useful to be able to create a new "instance of an object" without the constructor function running. You can inherit from a class without running the class's constructor function like so (almost like manually doing child.__proto__ = parent):
function inheritFrom(Class) {
function F() {};
F.prototype = Class.prototype;
return new F();
}
A better way to do this now is Object.setPrototypeOf().
The accepted answer missed the most important distinctions between prototypes and methods bound to a specific object, so I'm going to clarify
Prototype'd functions are only ever declared once. Functions attached using
this.method = function(){}
are redeclared again and again whenever you create an instance of the class. Prototypes are, thus, generally the preferred way to attach functions to a class since they use less memory since every instance of that class uses the same functions. As Erik pointed out, however, functions attached using prototypes vs attached to a specific object have a different scope, so prototypes don't have access to "private" variables defined in a function constructor.
As for what a prototype actually is, since it's an odd concept coming from traditional OO languages:
Whenever you create a new instance of a function:
var obj = new Foo();
the following logic is run (not literally this code, but something similar):
var inheritsFrom = Foo,
objectInstance = {};
objectInstance.__proto__ = inheritsFrom.prototype;
inheritsFrom.apply( objectInstance, arguments );
return objectInstance;
so:
A new object is created, {}, to represent the new instance of the function
The prototype of the function is copied to __proto__ of the new object. Note that this is a copy-by-reference, so Foo.prototype and objectInstance.__proto__ now refer to the same object and changes made in one can be seen in the other immediately.
The function is called with this new object being set as this in the function
and whenever you try to access a function or property, e.g.: obj.bar(), the following logic gets run:
if( obj.hasOwnProperty('bar') ) {
// use obj.bar
} else if( obj.__proto__ ){
var proto = obj.__proto__;
while(proto){
if( proto.hasOwnProperty('bar') ){
// use proto.bar;
}
proto = proto.__proto__;
}
}
in other words, the following are checked:
obj.bar
obj.__proto__.bar
obj.__proto__.__proto__.bar
obj.__proto__.__proto__.__proto__.bar
... etc
until __proto__ eventually equals null because you've reached the end of the prototype chain.
Many browsers actually expose __proto__ now, so you can inspect it in Firebug or the Console in Chrome/Safari. IE doesn't expose it (and may very well have a different name for the same thing internally).