objects.js | |
---|---|
Objects in JavaScript | |
Creating objects without constructors | console.log('Creating objects without constructors\n\n') |
We can create objects without constructors, just POJO (plain old javascript objects). | |
Define an object | var obj = {
aProperty: 'bar',
aMethod: function (val) {
return val*val;
}
} |
Assert some things about it. This is exactly as we would expect, and most people are used to. | console.dir( obj ) //=> { aProperty: 'bar', aMethod => [Function] }
console.log( obj.aProperty ); //=> 'bar'
console.log( obj.aMethod(2) ) //=> 4 |
This style of object is okay, but it's more like a data-structure than an object. It's hard to create new instances of our object without cloning it. | |
Using a constructor | console.log('Using a constructor\n\n') |
We can use a constructor function to construct new instances of our "class". | |
My constructor function. There is nothing special about constructor functions, only context. Generally if a function is going to be used as a constructor it is capitalized (but only by convention.
When a function is used as a constructor, | function MyObject() {
this.aProperty = 'bar'
this.aMethod = function (val) {
return val*val
} // We don't need to return anything if it's being used as a constructor
} |
Construct a new instance | var obj = new MyObject(); |
Everything works just as it did for our object literal above. | console.dir( obj ); //=> { aProperty: 'bar', aMethod => [Function] }
console.log( obj.aProperty ); //=> 'bar'
console.log( obj.aMethod(2) ); //=> 4 |
There is nothing special about constructors | console.log( 'There is nothing special about constructors\n\n' ); |
A constructor is just a function. It's use "as a constructor" is defined by the use of the | function AnotherObject() {
console.log( '`this is` ', this );
this.foo = 'bar'
} |
Calling with a constructor as normal, creates a new object | var obj = new AnotherObject() // logs "`this` is {}"
console.log( obj.foo ) //=> 'bar' |
We can call a constructor without the | obj = AnotherObject() // logs "`this` is > Window"
console.log( obj ) //=> undefined since AnotherMethod() doesn't return anything |
Returning from a constructor | console.log( 'Returning from a constructor\n\n' ); |
Normally we don't need to explicitly return anything from a constructor. This isn't really magic: inside the constructor | |
But we can if we like explicitly return objects from our constuctor. | console.log( 'But we _can_ if we like explicitly return objects from our constuctor\n\n' ); |
If an object is returned from the constructor it will be returned by the new keyword instead of our newly created object | function MyConstructor() {
this.foo = 'bar'; // this effectively does nothing as we return an explicit object
return { foo: "A different object" };
}
var obj = new MyConstructor()
console.log( obj.foo ) //=> "A different object" |
If the object returned is a string/number/etc it will not be returned instead | |
So here, the fact we return 10 is ignored. | function MyConstructor2() {
this.foo = 'bar';
return 10;
}
var obj = new MyConstructor2()
console.log( obj ) //=> { foo: 'bar' } (not 10!) |
This is subtly different though. Here we are returning an object not a literal, so it is returned instead. | function MyConstructor3() {
this.foo = 'bar';
return new String("A string object");
}
var obj = new MyConstructor3();
console.log( obj ) //=> > String("A string object") |
Prototypes | console.log('Prototypes'); |
When we call a method or look for a property that doesn't exist on an object, JavaScript will also look at the object's [[prototype]], to see the method or property exists there, and so on up the prototype chain. | |
In general we cannot access the prototype of an object. But we can modify the prototype of a constructor. (Confusing huh?!). | |
When we construct an object (with the | |
Basic prototype example | console.log('Basic prototype example'); |
Create a constructor function | function Animal() {} |
Add some, properties/methods to the constructor function's prototype | Animal.prototype.name = "animal"
Animal.prototype.talk = function() {
console.log("I am ", this.name);
} |
Construct a new animal | dog = new Animal() |
We have an apparently empty object | console.log(dog); //=> {} |
Set the | dog.name = "Rover"
console.log(dog) //=> { name: "Rover" } |
Our | dog.talk() //=> I am Rover |
In some implementations of JS (node/chrome/firefox/opera) we can lookup/modify an objects prototype directly with the | console.log( dog ) //=> { name: "Rover" }
console.log( dog.__proto__ ) //=> { name: "animal", talk: [Function] } |
The | console.log('The `new` keyword\n\n') |
We have now seen everything we need to, to know how the
| |
This means we could define our own function to replicate the behaviour of | function myNew(constructorFunction) {
var newObject = {};
newObject.__proto__ = constructorFunction.prototype;
var constructorReturned = constructorFunction.apply(newObject);
if ( typeof constructorReturned === 'object' ) {
return constructorReturned;
} else {
return newObject;
}
}
function Animal() {}
Animal.prototype.name = "an animal";
Animal.prototype.greet = function() {
return "Hi I am " + this.name;
} |
With the normal | dog = new Animal();
dog.name = "Rover"
console.log( dog ); //=> { name: "Rover" }
console.log( dog.greet() ); //=> "Hi I am Rover" |
With my | dog = myNew( Animal );
dog.name = "Rover"
console.log( dog ); //=> { name: "Rover" }
console.log( dog.greet() ); //=> "Hi I am Rover" |
So when/where/why prototypes? | console.log('So when/where/why prototypes?\n\n'); |
Prototypes let us mimic inheritance chains like in a regular OO language. | console.log('Prototypes let us mimic inheritance chains like in a regular OO language.\n\n');
function Animal() {}
Animal.prototype.legs = null
Animal.prototype.greet = function() { console.log("Hi I have ", this.legs, "legs") }; |
Note here, that we are setting the prototype to an instance of an animal. Prototypes are just objects. Nothing more, nothing less. | function Dog() {}
Dog.prototype = new Animal();
Dog.prototype.legs = 4
Dog.prototype.breed = null
function Retriever() {}
Retriever.prototype = new Dog();
Retriever.prototype.breed = "Retriever"
myDog = new Retriever();
console.log( myDog.breed ); //=> "Retriever"
myDog.greet() //=> logs "Hi I have 4 legs"
|