I'm learning JavaScript and I just came up with this thought
Why do I need 'new' to create an object?
function a(){};
var b = new a();
var c = {};
c.__proto__ = a.prototype;
If I create an object and point it's __proto__ to the constructor's prototype.
Is it the same way to create an object using new?
In your scenario, they would be equivalent (although __proto__ has been historically discouraged because it wasn't properly standardized), but only because the definition of a is empty.
If a would perform some initialization, it would not be done for c.
As for why new is necessary, the difference between calling a() and new a() would be the context object (this would be the global object or the newly created object).
In principle, you do not need anything. Javascript just has slightly different ways of creating objects which (of course) work slightly different. In your examples:
function a() = {}; // syntax error, correct syntax is function a() {}
var b = new a(); // creates a new instance of a - assuming a is a constructor function
var c = {}; // creates a new object literal
c.__proto__ = a.prototype // assings the prototype of function a to __proto__ of c
As a basic rule of thumb, if you simply want to create an object use the object literal way. If you want to use the constructor pattern you wanna use the new keyword to create instances using the constructor - you can also create instances manually but new is syntactic sugar. I would try to avoid directly assigning objects to the __proto__ since that is usually done internally. Another way to create objects based on other objects is using Object.create({}).
The latest ES syntax introduces the class keyword to abstract out the constructor pattern. This is a polarizing feature of the language. Read more here.
Hope it helps, happy learning!
firstly,the __proto__ only support on safari,chrome,firefox,not supported by IE,and which has not yet become a standard.
function Animal(name) {
this.name = name;
}
Animal.prototype.run = function() {
console.log(this.name + 'can run...');
}
var cat = new Animal('cat');
to simulation the new process as below:
//Simulation process
new Animal('cat')=function(){
let obj={}; //create an empty object
obj.__proto__=Animal.prototype;
//obj->Animal.prototype->Object.prototype->null
return Animal.call(obj,'cat');// bind this to the instantiated object
}
Related
What does the following code do:
WeatherWidget.prototype = new Widget;
where Widget is a constructor, and I want to extend the Widget 'class' with a new function WeatherWidget.
What is the new keyword doing there and what would happen if it is left out?
WeatherWidget.prototype = new Widget;
The new keyword calls Widget as a constructor and the return value is assigned to the prototype property. (If you would omit new, you would not call Widget unless you added an argument list, (). However, calling Widget that way might not be possible. It would certainly have the potential to spoil the global namespace if it is not strict mode code and the implementation is conforming to ECMAScript Ed. 5.x there, because then this in the constructor would refer to ECMAScript’s global object.)
But this approach actually comes from a really viral bad example in the old Netscape JavaScript 1.3 Guide (mirrored at Oracle, formerly Sun).
This way, your WeatherWidget instances will all inherit from the same Widget instance. The prototype chain will be:
[new WeatherWidget()] → [new Widget()] → [Widget.prototype] → …
This can be useful, but most of the time you would not want it to happen. You should not do that here unless you want all your WeatherWidget instances to share among them the property values they inherit from this Widget instance, and only through it, from Widget.prototype. Another problem is that you need to call the parent constructor this way, which may not allow to be called without arguments as you do, or would not initialize properly. It certainly has nothing to do with emulation of class-based inheritance as known, e.g., from Java.
The proper way to implement class-based inheritance in these prototype-based languages is (originally devised by Lasse Reichstein Nielsen in comp.lang.javascript in 2003, for cloning objects):
function Dummy () {}
Dummy.prototype = Widget.prototype;
WeatherWidget.prototype = new Dummy();
WeatherWidget.prototype.constructor = WeatherWidget;
The constructor prototype property should be fixed as well, so that your WeatherWidget instances w would have w.constructor === WeatherWidget as expected, and not w.constructor === Widget. However, be aware that it is enumerable afterwards.
This way, WeatherWidget instances will inherit properties through the prototype chain, but will not share property values among them, because they inherit from Widget.prototype through Dummy which has no own properties:
[new WeatherWidget()] → [new Dummy()] → [Widget.prototype] → …
In implementations of ECMAScript Ed. 5 and later, you can and should use
WeatherWidget.prototype = Object.create(Widget.prototype, {
constructor: {value: WeatherWidget}
});
instead. This has the additional advantage that the resulting constructor property is not writable, enumerable, or configurable.
The parent constructor will only be called if you call it explicitly, from WeatherWidget, for example with
function WeatherWidget (…)
{
Widget.apply(this, arguments);
}
See also Function.prototype.extend() in my JSX:object.js for how to generalize this. Using that code, it would become
WeatherWidget.extend(Widget);
My Function.prototype.extend() takes an optional second argument with which you can easily augment the prototype of WeatherWidget instances:
WeatherWidget.extend(Widget, {
foo: 42,
bar: "baz"
});
would be equivalent to
WeatherWidget.extend(Widget);
WeatherWidget.prototype.foo = 42;
WeatherWidget.prototype.bar = "baz";
You will still need to call the parent constructor explicitly in the child constructor, though; that part cannot reasonably be automated. But my Function.prototype.extend() adds a _super property to the Function instance which makes it easier:
function WeatherWidget (…)
{
WeatherWidget._super.apply(this, arguments);
}
Other people have implemented similar extensions.
According to some odd Javascript rules, new Widget actually invokes the constructor rather than returning a reference to the constructor. This question actually answers the question the difference between var a = new Widget() and var a = Widget().
In simple words, the new keyword tells Javascript to call the function Widget under a different set of rules than a regular function call. Going off the top of my head, the ones I remember are:
There is a brand new object created
Widget can use the this keyword to refer to that object.
If Widget does not return anything, this new object will be created.
This object will inherit a few additional properties that will indicate it was created by Widget that are used to track down property chains.
Without the new keyword, a call to widget would
If in strict mode, this will be set to undefined.
Otherwise, this will refer to the global object. (Called window by the browser.)
If the function does not return anything, then undefined will be returned.
Reference:
new keyword
WeatherWidget.prototype = new Widget;
does create a new instance of the Widget constructor and use it as WeatherWidget's prototype object. Using the new keyword creates the new object, sets up the inheritance chain of it to Widget.prototype, and applies the constructor function on it (where you can set up individual properties'n'methods, or create private-scoped variables).
Without the new keyword it would be an assignment of the Widget function to the prototype property - which does not make any sense. If you'd add the optional brackets (i.e. Widget()), it would invoke the function normally, but not as a constructor on a new instance, but with the global object as context. See also the reference for the this keyword.
Notice that you should not really use this code. As said, it creates a new instance by invoking the constructor function. But the purpose is only to create an empty object that inherits from the Widgets prototype object, not to instantiate something (which could do some harm, depending on the code). Instead, you should use Object.create (or its popular shim):
WeatherWidget.prototype = Object.create(Widget.prototype);
see also Javascript basic inheritance vs Crockford prototypical inheritance
In plain english you're extending one class with another. A prototype can only be an object so you set WeatherWidget's prototype to a new instance of Widget. If you removed the new keyword you would be setting the prototype to the literal constructor function which doesn't do anything.
var Appendages = function(){
this.legs = 2
};
var Features = function() {
this.ears = 4;
this.eyes = 1;
}
// Extend Features class with Appendages class.
Features.prototype = new Appendages;
var sara = new Features();
sara.legs;
// Returns 2.
Understanding that the prototype can be any object, something like this would also work:
var appendages = {
legs : 2
};
var Features = function() {
this.ears = 4;
this.eyes = 1;
}
// Extend Features class with Appendages class.
Features.prototype = appendages;
var sara = new Features();
sara.legs;
// Returns 2.
In JavaScript, if the key isn't found on the object, it checks the parents object you extended it from. Hence you can change items on the parent object on the fly like so:
var appendages = {
legs : 2
};
var Features = function() {
this.ears = 4;
this.eyes = 1;
}
// Extend Features class with Appendages class.
Features.prototype = appendages;
var sara = new Features();
sara.legs;
// Returns 2.
appendages.hair = true;
sara.hair;
// Returns true.
Note that this all happens during instantiation which means you can't just switch out the prototype after you've created the object:
var foo = {name : 'bob'};
var bar = {nachos : 'cheese'};
foo.prototype = bar;
foo.nachos;
// undefined
However, all modern browsers come with this newer __proto__ method, which allows you to do it:
var foo = {name : 'bob'};
var bar = {nachos : 'cheese'};
foo.__proto__ = bar;
foo.nachos
// "cheese"
Read up more on understanding JavaScript prototypes here.
This article from Pivotal Labs is also really good.
new is important for prototype inheritance; i.e.
Create a constructor with a method
var Obj = function(){};
Obj.prototype = {};
Obj.prototype.foo = function(){console.log('foo');};
Make a second constructor to extend the first with
var ExObj = function(){};
Now, if we prototype without new,
ExObj.prototype = Obj;
(new ExObj).foo(); // TypeError: Object #<Object> has no method 'foo'
Which means we haven't inherited from the prototype of Obj, however, if we prototype with new
ExObj.prototype = new Obj();
(new ExObj).foo(); // console logs 'foo'
Furthermore, adding new things to the prototype of ExObj doesn't make any changes to it's base, Obj.
JavaScript functions are "MULTIPLE(2) PERSONALITIES"!!!
They are regular-functions with input and output, which we call like function().
Also they are constructors of JS-objects, when we use the new keyword. >>>BUT<<< the new created objects are NOT INSTANCES of the constructors (like the objects of classes in class-based inheritance). The new objects are instances of the object of the prototype property of the constructor.
Then in WeatherWidget.prototype = you put the object you want to inherit its properties to the objects the constructor will create, which usually is new function() and not a function.
JavaScript created HUGE confusion in the programming community by naming the objects created by constructors, INSTANCES of them with the instanceof keyword.
> function f(){}
undefined
> new f() instanceof f
true
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’
What does the following code do:
WeatherWidget.prototype = new Widget;
where Widget is a constructor, and I want to extend the Widget 'class' with a new function WeatherWidget.
What is the new keyword doing there and what would happen if it is left out?
WeatherWidget.prototype = new Widget;
The new keyword calls Widget as a constructor and the return value is assigned to the prototype property. (If you would omit new, you would not call Widget unless you added an argument list, (). However, calling Widget that way might not be possible. It would certainly have the potential to spoil the global namespace if it is not strict mode code and the implementation is conforming to ECMAScript Ed. 5.x there, because then this in the constructor would refer to ECMAScript’s global object.)
But this approach actually comes from a really viral bad example in the old Netscape JavaScript 1.3 Guide (mirrored at Oracle, formerly Sun).
This way, your WeatherWidget instances will all inherit from the same Widget instance. The prototype chain will be:
[new WeatherWidget()] → [new Widget()] → [Widget.prototype] → …
This can be useful, but most of the time you would not want it to happen. You should not do that here unless you want all your WeatherWidget instances to share among them the property values they inherit from this Widget instance, and only through it, from Widget.prototype. Another problem is that you need to call the parent constructor this way, which may not allow to be called without arguments as you do, or would not initialize properly. It certainly has nothing to do with emulation of class-based inheritance as known, e.g., from Java.
The proper way to implement class-based inheritance in these prototype-based languages is (originally devised by Lasse Reichstein Nielsen in comp.lang.javascript in 2003, for cloning objects):
function Dummy () {}
Dummy.prototype = Widget.prototype;
WeatherWidget.prototype = new Dummy();
WeatherWidget.prototype.constructor = WeatherWidget;
The constructor prototype property should be fixed as well, so that your WeatherWidget instances w would have w.constructor === WeatherWidget as expected, and not w.constructor === Widget. However, be aware that it is enumerable afterwards.
This way, WeatherWidget instances will inherit properties through the prototype chain, but will not share property values among them, because they inherit from Widget.prototype through Dummy which has no own properties:
[new WeatherWidget()] → [new Dummy()] → [Widget.prototype] → …
In implementations of ECMAScript Ed. 5 and later, you can and should use
WeatherWidget.prototype = Object.create(Widget.prototype, {
constructor: {value: WeatherWidget}
});
instead. This has the additional advantage that the resulting constructor property is not writable, enumerable, or configurable.
The parent constructor will only be called if you call it explicitly, from WeatherWidget, for example with
function WeatherWidget (…)
{
Widget.apply(this, arguments);
}
See also Function.prototype.extend() in my JSX:object.js for how to generalize this. Using that code, it would become
WeatherWidget.extend(Widget);
My Function.prototype.extend() takes an optional second argument with which you can easily augment the prototype of WeatherWidget instances:
WeatherWidget.extend(Widget, {
foo: 42,
bar: "baz"
});
would be equivalent to
WeatherWidget.extend(Widget);
WeatherWidget.prototype.foo = 42;
WeatherWidget.prototype.bar = "baz";
You will still need to call the parent constructor explicitly in the child constructor, though; that part cannot reasonably be automated. But my Function.prototype.extend() adds a _super property to the Function instance which makes it easier:
function WeatherWidget (…)
{
WeatherWidget._super.apply(this, arguments);
}
Other people have implemented similar extensions.
According to some odd Javascript rules, new Widget actually invokes the constructor rather than returning a reference to the constructor. This question actually answers the question the difference between var a = new Widget() and var a = Widget().
In simple words, the new keyword tells Javascript to call the function Widget under a different set of rules than a regular function call. Going off the top of my head, the ones I remember are:
There is a brand new object created
Widget can use the this keyword to refer to that object.
If Widget does not return anything, this new object will be created.
This object will inherit a few additional properties that will indicate it was created by Widget that are used to track down property chains.
Without the new keyword, a call to widget would
If in strict mode, this will be set to undefined.
Otherwise, this will refer to the global object. (Called window by the browser.)
If the function does not return anything, then undefined will be returned.
Reference:
new keyword
WeatherWidget.prototype = new Widget;
does create a new instance of the Widget constructor and use it as WeatherWidget's prototype object. Using the new keyword creates the new object, sets up the inheritance chain of it to Widget.prototype, and applies the constructor function on it (where you can set up individual properties'n'methods, or create private-scoped variables).
Without the new keyword it would be an assignment of the Widget function to the prototype property - which does not make any sense. If you'd add the optional brackets (i.e. Widget()), it would invoke the function normally, but not as a constructor on a new instance, but with the global object as context. See also the reference for the this keyword.
Notice that you should not really use this code. As said, it creates a new instance by invoking the constructor function. But the purpose is only to create an empty object that inherits from the Widgets prototype object, not to instantiate something (which could do some harm, depending on the code). Instead, you should use Object.create (or its popular shim):
WeatherWidget.prototype = Object.create(Widget.prototype);
see also Javascript basic inheritance vs Crockford prototypical inheritance
In plain english you're extending one class with another. A prototype can only be an object so you set WeatherWidget's prototype to a new instance of Widget. If you removed the new keyword you would be setting the prototype to the literal constructor function which doesn't do anything.
var Appendages = function(){
this.legs = 2
};
var Features = function() {
this.ears = 4;
this.eyes = 1;
}
// Extend Features class with Appendages class.
Features.prototype = new Appendages;
var sara = new Features();
sara.legs;
// Returns 2.
Understanding that the prototype can be any object, something like this would also work:
var appendages = {
legs : 2
};
var Features = function() {
this.ears = 4;
this.eyes = 1;
}
// Extend Features class with Appendages class.
Features.prototype = appendages;
var sara = new Features();
sara.legs;
// Returns 2.
In JavaScript, if the key isn't found on the object, it checks the parents object you extended it from. Hence you can change items on the parent object on the fly like so:
var appendages = {
legs : 2
};
var Features = function() {
this.ears = 4;
this.eyes = 1;
}
// Extend Features class with Appendages class.
Features.prototype = appendages;
var sara = new Features();
sara.legs;
// Returns 2.
appendages.hair = true;
sara.hair;
// Returns true.
Note that this all happens during instantiation which means you can't just switch out the prototype after you've created the object:
var foo = {name : 'bob'};
var bar = {nachos : 'cheese'};
foo.prototype = bar;
foo.nachos;
// undefined
However, all modern browsers come with this newer __proto__ method, which allows you to do it:
var foo = {name : 'bob'};
var bar = {nachos : 'cheese'};
foo.__proto__ = bar;
foo.nachos
// "cheese"
Read up more on understanding JavaScript prototypes here.
This article from Pivotal Labs is also really good.
new is important for prototype inheritance; i.e.
Create a constructor with a method
var Obj = function(){};
Obj.prototype = {};
Obj.prototype.foo = function(){console.log('foo');};
Make a second constructor to extend the first with
var ExObj = function(){};
Now, if we prototype without new,
ExObj.prototype = Obj;
(new ExObj).foo(); // TypeError: Object #<Object> has no method 'foo'
Which means we haven't inherited from the prototype of Obj, however, if we prototype with new
ExObj.prototype = new Obj();
(new ExObj).foo(); // console logs 'foo'
Furthermore, adding new things to the prototype of ExObj doesn't make any changes to it's base, Obj.
JavaScript functions are "MULTIPLE(2) PERSONALITIES"!!!
They are regular-functions with input and output, which we call like function().
Also they are constructors of JS-objects, when we use the new keyword. >>>BUT<<< the new created objects are NOT INSTANCES of the constructors (like the objects of classes in class-based inheritance). The new objects are instances of the object of the prototype property of the constructor.
Then in WeatherWidget.prototype = you put the object you want to inherit its properties to the objects the constructor will create, which usually is new function() and not a function.
JavaScript created HUGE confusion in the programming community by naming the objects created by constructors, INSTANCES of them with the instanceof keyword.
> function f(){}
undefined
> new f() instanceof f
true
In Simple words why we use prototype.constructor. I am reading an article about inheritance where I saw prototype.constructor. I see no difference in result when I comment that code. So my question why and when to use it practically.
function Mammal(name){
this.name=name;
this.action= function (){
alert('0')
}
}
function Cat(name){
this.name=name;
}
Cat.prototype = new Mammal();
//Cat.prototype.constructor=Cat; // Otherwise instances of Cat would have a constructor of Mammal
Cat.prototype.action=function(){
alert('1')
}
var y= new Mammal()
var x= new Cat()
y.action()
x.action()
It's mostly convention. Although nothing in JavaScript itself uses the constructor property, sometimes people use it in their code, assuming that it will refer back to the object's constructor. It's not just convention anymore, see ¹ for details.
When you create a function:
function Cat() {
}
The function starts out with an object on its prototype property that has a property called constructor that points back to the function:
console.log(Cat.prototype.constructor === Cat); // true
This is in the specification. (It's also the only place in the specification that property is mentioned — e.g., JavaScript, itself, makes no use of this property at all. Not anymore.¹)
Consequently, instances created with that prototype (whether created via the constructor function or other ways) inherit that constructor property:
var c = new Cat();
console.log(c.constructor === Cat); // true
var c2 = Object.create(Cat.prototype);
console.log(c2.constructor === Cat); // true, even though Cat wasn't used
When you replace the prototype property on a function, as you typically do when building hierarchies:
Cat.prototype = new Mammal(); // This is an anti-pattern, btw, see below
...you end up with an object on Cat.prototype where constructor points to Mammal. Since that's not what one normally expects, it's customary to fix it:
Cat.prototype.constructor = Cat;
Although nothing in JavaScript itself uses the property (it does now¹), sometimes people use it in their code, assuming that it will refer back to the object's constructor.
Re the anti-pattern in that code: When using constructor functions to build a hierarchy, it's not best practice to actually call the "base" constructor to create the "derived" constructor's prototype. Instead, use Object.create to create the prototype:
Cat.prototype = Object.create(Mammal.prototype);
Cat.prototype.constructor = Cat;
...and then chain to Mammal in Cat:
function Cat() {
Mammal.call(this);
// ...
}
Why do it that way? Consider: What if the base requires arguments you won't get until construction-time to meaningfully initialize an instance? You can't pass it arguments until you have them. The pattern above allows you to handle that situation.
Note that Object.create was added in ES5 and so is missing from some old browsers (like IE8). The single-argument version of it can be shimmed/polyfilled trivially, though:
if (!Object.create) {
Object.create = function(proto, props) {
if (typeof props !== "undefined") {
throw new Error("The second argument of Object.create cannot be shimmed.");
}
function f() { }
f.prototype = proto;
return new f;
};
}
I'll just note that constructor functions are just one way of building object hierarchies in JavaScript. They're not the only way, because JavaScript uses prototypical inheritance. JavaScript is so powerful you can use constructor functions to get something similar to class-like inheritance, but it also lets you do more traditional prototypical-style inheritance directly.
¹ "Although nothing in JavaScript itself uses the constructor property..." That's not true anymore as of ES2015 (aka "ES6"). Now, the constructor property is used in a couple of places (such as the SpeciesConstructor and ArraySpeciesCreate abstract operations), which are used in various classes that have methods returning new instances of the class, such as Array#slice and Promise#then. It's used in those places to ensure that subclasses work correctly: E.g., if you subclass Array, and use slice on an instance of the subclass, the array returned by slice is an instance of your subclass, not a raw Array — because slice uses ArraySpeciesCreate.
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.