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.
Related
I created a class using function like -
function Person(name) {
this.name = name;
}
var obj = new Person("Ferdinand");
console.log(obj.name);
I am creating an object obj and prints its property name it is working fine and prints "Ferdinand", but if we forget to write new key word like below program -
function Person(name) {
this.name = name;
}
var obj = Person("Ferdinand");
console.log(name);
Here I am not able to understand why name is available in console, it is printing "Ferdinand". But we are using Person as a function and assigning name variable in function itself so why its value is available outside function.
JavaScript does not implement objects in the classical sense. Instead, they are implemented directly:
var thing={}; // new object
Because you typically want multiple objects to follow a common pattern and behaviour, you can use what is called a constructor function to help. In your example, Person is a constructor function.
When using a constructor, you call it indirectly using the new command:
var thing = new Person(…);
In fact, there’s a lot of magic going on here:
JavaScript begins by creating a new object: var thing={};.
Then the this key word is assigned to the new object
Finally the constructor is run, using the this value to assign local values.
If you call a constructor function directly, the first 2 steps do not apply, and the function is left trying to work in its own definition of this which is generally not what you want.
If you really want to call the constructor function without bothering with new, you can try the following:
function Person(data) {
// “new” safe constructor
if(!(this instanceof Person)) {
return new Person(data);
}
This new version checks whether it is being called as a proper constructor, and, if not, calls itself properly.
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'm not understanding why in the following code, obj.BaseMethod doesn't return the method defined in BaseClass constructor. In other words, why is it that
SubClass.prototype.BaseMethod
is defined, but
new SubClass().prototype.BaseMethod
is undefined.
http://jsfiddle.net/HvxJ4/4/
I'm obviously missing something important here.
function BaseClass() {
var privatestuff = "blah";
return {
BaseMethod: function() {
console.log('BaseMethod called');
}
}
}
function SubClass() {
var moreprivates = "stuff";
return {
SubClassMethod: function() {
console.log('SubClassMethod called');
}
}
}
SubClass.prototype = new BaseClass();
var obj = new SubClass();
obj.SubClassMethod(); // SubClassMethod called
obj.BaseMethod(); // Uncaught TypeError: undefined is not a function
UPDATE
I actually understood how to get my code working using
this.method = function() { }
in my constructor function. I just didn't understand why the code above didn't do the same thing.
The answer is that if you return an object in a constructor function, you are no longer using "protoypal" inheritance.
The thing that makes this most clear to me was this answer
https://stackoverflow.com/a/2118831/834770
Quoting Douglas Crockford in Chapter 5, Inheritance, of JavaScript:
(...)
Douglas Crockford then explains how the new operator could be
implemented as a JavaScript function. This function makes use of
several other functions defined in the book, so I rewrote it in a
(somewhat) simpler form below:
function createNew(constructor) {
// a function to explain the new operator:
// var object = createNew(constructor);
// is equivalent to
// var object = new constructor();
//
// param: constructor, a function
// return: a new instance of the "constructor" kind of objects
// step 1. create a new empty object instance
// linked to the prototype of provided constructor
var hiddenLink = function(){};
hiddenLink.prototype = constructor.prototype;
var instance = new hiddenLink(); // cheap trick here: using new to implement new
// step 2. apply the constructor the new instance and get the result
var result = constructor.apply(instance); // make this a reference to instance within constructor
// step 3. check the result, and choose whether to return it or the created instance
if (typeof result === 'object') {
return object;
} else {
return instance;
}
}
So, in short, if you return an object in this function, then the inheritance bit is effectively ignored.
Here's a way to think of the statement
new SubClass().prototype.BaseMethod
First, the new keyword tells JavaScript to create a new, empty object, i.e. {}
Then JavaScript sets the context (this) to be equal to that new object and calls the function after new. So in this case JavaScript will look for a function to call, but your syntax doesn't reference a defined function, so the result is undefined.
Contrast that with a typical approach for defining objects in JavaScript:
function ExampleObject() {
// stuff related to the example object
this.exampleProperty = "value";
}
var exObj = new ExampleOject();
In this case new creates the empty object {} as before, but now there is a defined function to call. When this function is called, the newly created object (set equal to this) will have an exampleProperty set equal to "value". The resulting object is then assigned to the variable exObj.
It may sound strange to those coming from a Java background (or similar), but JavaScript doesn't really support the concept of classes. The language made the unfortunate choice of trying to make it's prototypical inheritance look like classical inheritance, but it's really not the same. If you're going to be spending a lot of time in JavaScript, you might want to stop trying to think in terms of classes and subclasses and learn a bit about prototypes instead.
I'm trying to understand some code Mozilla put out on constructor chaining. I've added comments to the parts I think I understand, but I'm still not clear on everything that's going on here. Can someone explain line by line what is going on in this code?
// Using apply() to chain constructors.
Function.prototype.construct = function (aArgs) {
// What is this line of code doing?
var fConstructor = this, fNewConstr = function () { fConstructor.apply(this, aArgs); };
// Assign the function prototype to the new function constructor's prototype.
fNewConstr.prototype = fConstructor.prototype;
// Return the new function constructor.
return new fNewConstr();
};
// Example usage.
function MyConstructor () {
// Iterate through the arguments passed into the constructor and add them as properties.
for (var nProp = 0; nProp < arguments.length; nProp++) {
this["property" + nProp] = arguments[nProp];
}
}
var myArray = [4, "Hello world!", false];
var myInstance = MyConstructor.construct(myArray);
// alerts "Hello world!"
alert(myInstance.property1);
// alerts "true"
alert(myInstance instanceof MyConstructor);
// alerts "MyConstructor"
alert(myInstance.constructor);
The original code can be found here.
Basically, this is an alternate way to call a constructor function, which gives you the opportunity to wrap the constructor call in another function. I'll focus on the line you are confused about. fConstructor is set to this, which references our original constructor function, in this example that is MyConstructor. fNewConstr is the constructor which will override the original constructor. Within that fNewConstr you could implement additional code not found in the MyConstructor. Within fNewConstr, we call fConstructor using the Function apply method, passing this as the context, and the aArgs array passed to the construct method. Then we set the prototype of the fNewConstr to the fConstructor prototype to complete the inheritance chain. Finally, we return a new instance of fNewConstr. Prefixing the new keyword to a function call creates a new object, sets its prototype to the prototype of the function, and invokes the function in the context of the new item. Because we apply the fConstructor method with the fNewConstr's context, the result is essentially the same as calling new MyConstructor(). Make sense? Or do I need to go into more detail.
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.