6.
Objects
Manu Dube
Objects
• JavaScript has primitives and objects as data-types
• Any data-type that is not a primitive is an object
–primitives can behave as immutable objects
● Methods are applied to wrapper objects
–objects are mutable and are manipulated by reference
● var y = x; means y holds a reference to x, not a copy
• An object is a composite value
–it contains multiple values which you can retrieve by name
–property names are strings
–values can be primitives or other objects
–it is unordered
–it is a type of string to value mapping
● More than a simple map, as it also inherits properties from prototype
–JavaScript uses prototypal inheritance
● Objects are dynamic and properties can be added and deleted
Objects Manu Dube
Example: Math Object
In addition to basic operators such as +, -, *, / we can use the Math object
•
Math.pow(2,53) // => 9007199254740992: 2 to the power 53
Math.round(.6) // => 1.0: round to the nearest integer
Math.ceil(.6) // => 1.0: round up to an integer
Math.floor(.6) // => 0.0: round down to an integer
Math.abs(-5) // => 5: absolute value
Math.max(x,y,z) // Return the largest argument
Math.min(x,y,z) // Return the smallest argument
Math.random() // Pseudo-random number x where 0 <= x < 1.0
Math.PI // π: circumference of a circle / diameter
Math.E // e: The base of the natural logarithm
Math.sqrt(3) // The square root of 3
Math.pow(3, 1/3) // The cube root of 3
Math.sin(0) // Trigonometry: also Math.cos, Math.atan, etc.
Math.log(10) // Natural logarithm of 10
Math.log(100)/Math.LN10 // Base 10 logarithm of 100
Math.log(512)/Math.LN2 // Base 2 logarithm of 512
Math.exp(3) // Math.E cubed
Objects Manu Dube
Types of Objects
Native objects are those defined by JavaScript
•
–arrays, functions, dates, regular expressions
Host objects are those defined by the host environment
•
–window, document, HTML elements
–can also be native at times
User-defined objects are those the programmer creates
•
Objects Manu Dube
Properties
A property is a name-value pair
•
–name can be a string, even empty string
● Two properties of an object cannot have the same name
–the value can be any value, even functions
Properties have associated attributes
•
–writable: whether the value can be set
–enumerable: whether the property name is returned by a for/in loop
–configurable: whether the property can be deleted or its attributes can be altered
Properties can be
•
–own: properties defined directly on an object
–inhertited: those defined by the object's prototype
Objects Manu Dube
Creating Objects
Can create an object
•
–using object literal
● property names that include spaces or hyphens, or are JavaScript keywords should be in quotes
–using keyword new
–using Object.create() function
Objects Manu Dube
Using Literals
var empty = {};
•
var point = {x:0, y:0};
•
var point2 = {x:point.x, y:point.y+1};
• //point.x is value of property x of object point
var book = {
•
"main title": "Hello World";
"sub title" : "My first program";
"for": "all audiences"
author: {
firstname: "Me",
lastname: "Myself"
};
Objects Manu Dube
Using new
The new operator creates and initializes an object
•
–must call constructor function
–native types have built-in constructors
–can define constructors for user-defined objects
var o = new Object();
• //empty object
var a = new Array();
• //empty array
var d = new Date();
• //Date object representing current time
Var r = new RegExp("ab")
• //create a regular expression for pattern matching
Objects Manu Dube
Prototypes
Almost all objects in JavaScript has an associated prototype
•
–in rare cases, null
–the object inherits properties from the prototype
All objects created by literals have the prototype Object.prototype
•
Object.prototype has no prototype
•
Built-in constructors have a prototype that inherits from Object.prototype
•
–Date.prototype inherits from Object.prototype
–a Date() object inherits from both
The linked series of prototypes is called a prototype chain
•
Objects Manu Dube
Using Object.create()
A static function, not a method invoked for objects
•
Takes two parameters
•
–the prototype for the object to be created
–optionally, properties of the new object
● can also use to change property attributes, such as writable
var o1 = Object.create({x:0, y:1}); //o1 inherits the properties x and y
•
var o2 = Object.create(null);
• //o2 does not inherit any properties or methods, not even basic ones
var o3 = Object.create(Object.prototype);
• // empty object, same as using {} or new Object()
<script>
var o1 = Object.create({x:0, y:1}, {r: {value: "p"}, y: {value:"q"}});
document.write(o1.x + "<BR>"+o1.y+ "<BR>"+o1.__proto__.y);
•</script>
Objects Manu Dube
Accessing and Creating Properties
Properties can be accessed using
•
–the . operator as in o1.x
–the [ ] operator as in o1["x"]
● the expression in the [ ] should be convertible to a string
–useful if wish to loop over properties such as address1, address2, ... or with for/in
–also if property value cannot be hardcoded, for instance if it must be input
● if you use a keyword, some implementations may require [" "]
It is possible to create new properties using these operators
•
<script>
var o1 = {a:5};
o1.x =1;
o1["y"]=2;
document.write(o1.a+"<BR>");
document.write(o1.x + "<BR>"+o1.y);
</script>
Objects Manu Dube
Deleting Properties
The delete operator removes a property from an object
•
The operator does not delete inherited properties
•
–if you delete property from prototype object, all objects that inherit from it are affected
A delete expression evaluates to true if it succeeded or there was nothing to delete
•
–unless in strict mode, attempting to delete a nonconfigurable property returns false
–properties of global objects including variable and function definitions are nonconfigurable
<script>
var o1 = {a:5};
o1.x =1;
o1["y"]=2;
var o2 = Object.create(o1);
var o3 = Object.create(o1);
document.write(delete o3.y+"<BR>");
document.write(delete o2+"<BR>");
delete o3.__proto__.x;
document.write(o2.a+"<BR>");
document.write((o2.x != undefined)?o2.x:"hello"+ "<BR>"+o1.y);
</script>
Objects Manu Dube
Testing Properties
JavaScript objects are sets of properties
•
Can test if object has a property with a given name
•
–in operator returns true if object has its own, or an inherited property by the name
–hasOwnProperty() and propertyIsEnumerable()
Could also test if property !== undefined
•
<script>
var o1 = {a:5};
o1.x =1;
var o2 = Object.create(o1);
o1["y"]=2;
document.write("a in o1: " + ("a" in o1) + "<BR>");
document.write("a in o2: " + ("a" in o2) + "<BR>");
document.write("a own in o1: "+ o1.hasOwnProperty("a") + "<BR>");
document.write("a own in o2: "+ o2.hasOwnProperty("a") + "<BR>");
document.write("y in o1: " + ("y" in o1) + "<BR>");
document.write("y in o2: " + ("y" in o2) + "<BR>");
document.write("y own in o1: "+ o1.hasOwnProperty("y") + "<BR>");
document.write("y own in o2: "+ o2.hasOwnProperty("y") + "<BR>");
document.write("deleting a in o1" + delete o1.a+"<BR>");
document.write("a in o1: " + ("a" in o1) + "<BR>");
document.write("a in o2: " + ("a" in o2) + "<BR>");
document.write("deleting y in o2" + delete o2.y+"<BR>");
document.write("y in o1: " + ("y" in o1) + "<BR>");
document.write("y in o2: " + ("y" in o2) + "<BR>");
</script>
Objects Manu Dube
Listing Properties
Built-in methods that are inherited are not enumerable
•
The properties you add are enumerable by default
•
–you could make them nonenumerable
–if you modify properties while constructing object via Object.create, make it enumerable
<script>
var o1 = {a:5, b:13, c:"hello"};
if("toString" in o1) document.write("toString is a property <BR>");
for (p in o1) document.write(p + ": " + o1[p] + "<BR>");
var o2 = Object.create(o1, {a: {value: 99}, c: {value: "hi!", enumerable: true}});
for (p in o2) document.write(p + ": " + o2[p] + "<BR>");
</script>
There are also functions Object.keys() and Object.getOwnPropertyNames()
•
–the first is for enumerable, the second also lists nonenumerable but not inherited
<script>
var o1 = {a:5, b:13, c:"hello"};
var o2 = Object.create(o1, {a: {value: 99}, c: {value: "hi!", enumerable: true}});
document.write(Object.keys(o1));
document.write("<BR>");
document.write(Object.getOwnPropertyNames(o2));
</script>
Objects Manu Dube
Methods
Property whose value is a function
•
–calling a method just involves adding () after name
–Can add, change and delete methods
<script>
var o1 = {a:5, b:13, c:"hello", d:function(){document.write("Hello World!")}};
o1.d();
o1.e=function(){document.write("Bye!")};
o1.e();
o1.d = function(){document.write("Now Goodbye")};
o1.d();
delete o1.d;
document.write(typeof o1.d);
</script>
Objects Manu Dube
this keyword
Method can use this within object to access properties
•
<script>
var myob = {
x:5,
y:10,
dist: function(){return Math.sqrt(this.x*this.x+this.y*this.y);}
}
document.write(myob.dist());
</script>
Objects Manu Dube
Getter and Setter Functions
The value of a property may be replaced by getter and setter functions
•
–for accessor properties rather than simply data properties that have a value
–when program queries a value, it invokes the getter method
–when program sets a value, it invokes the setter method
–such properties do not have a writable attribute, but are read if getter is defined and write if setter is
Can use literals to create getter and setter functions
•
<script>
var o1 = {
x:5,
get a() {return this.x*this.x;},
set a(n) {this.x=Math.sqrt(n);}
};
document.write(o1.x);
document.write("<BR>");
document.write(o1.a);
document.write("<BR>");
o1.a = 9;
document.write(o1.x);
</script>
Objects Manu Dube
Getter and Setter Using Property Descriptors
•Accessor properties do not have a value or writable attribute
•Attributes are get, set, enumerable and configurable
•Use Object.defineProperty() to add properties
•Use Object.getOwnPropertyDescriptor() to get attributes
–for inherited properties, have to go up the prototype chain
<script>
var o1 = {};
Object.defineProperty(o1, "x", {value: 5, enumerable: true, writable: true, configurable: true});
Object.defineProperty(o1, "a", {get: function(){return this.x*this.x},
set: function(n){this.x=Math.sqrt(n);}});
document.write(o1.x);
document.write("<BR>");
document.write(o1.a);
document.write("<BR>");
o1.a = 9;
document.write(o1.x);
document.write("<BR>");
document.write(Object.getOwnPropertyDescriptor(o1, "x"));
document.write("<BR>");
document.write(Object.getOwnPropertyDescriptor(o1, "a"));
document.write("<BR>");
document.write(Object.getOwnPropertyDescriptor(o1, "y"));
document.write("<BR>");
</script>
Objects Manu Dube
Getter and Setter Using Property Descriptors
<script>
var o1 = {};
Object.defineProperty(o1, "x", {value:5, enumerable: true,
writable: true, configurable: true});
Object.defineProperty(o1, "a", {get: function(){return
this.x*this.x;}, set: function(n){this.x = Math.sqrt(n);}});
document.write(o1.x);
document.write("<BR>");
document.write(o1.a);
document.write("<BR>");
o1.a = 9;
document.write(o1.x);
document.write("<BR>");
var k = Object.getOwnPropertyDescriptor(o1, "x");
document.write(k.value);
document.write("<BR>");
document.write(k.writable);
document.write("<BR>");
document.write(k.enumerable);
document.write("<BR>");
document.write(k.configurable);
document.write("<BR>");
</script>
Objects Manu Dube
Advantage of Constructor
• Can pass parameters to create object with different property values
• parameters passed could be functions
<script>
function doNothing(a,b,c){
this.work=a,
this.urgent=b,
this.mustdo=c,
this.toString=function(){return this.work+" "+this.urgent+" "+this.mustdo+"<BR>"}
}
var useless = new doNothing("nothing", "not at all", "why");
document.write(useless);
var useful = new doNothing("meditate", "now", "nothing");
document.write(useful);
</script>
Objects Manu Dube
Assignment operator
• Objects are assigned by reference
<script>
function doNothing(a,b,c){
this.work=a,
this.urgent=b,
this.mustdo=c
}
var useless = new doNothing("nothing", "not at all", "why");
var useful = useless;
useful.x = 4;
document.write(useless.x);
</script>
Objects Manu Dube
Equality of objects
• Equal if variables point to same object
<script>
function doNothing(a,b,c){
this.work=a,
this.urgent=b,
this.mustdo=c
}
var useless = new doNothing("nothing", "not at all", "why");
var useful = useless;
var copycat = new doNothing("nothing", "not at all", "why");
document.write(useful == useless);
document.write("<BR>");
document.write(useful == copycat);
</script>
Objects Manu Dube
Objects as function parameters
• Objects are passed by reference
<script>
function doNothing(a,b,c){
this.work=a,
this.urgent=b,
this.mustdo=c
}
var useless = new doNothing("nothing", "not at all", {must: "why", do: "not!"});
for(var i in useless)
document.write(i+" "+useless[i]+"<BR>");
var b={x:5, y:10};
var useful = new doNothing("abc", "def", b);
b.z = "hello";
document.write(useful.mustdo.z);
</script>
Objects Manu Dube
Object Attributes
• Object attributes include
• prototype
• the object from which the object inherits properties
• attribute is set when object is created
• literals use Object.prototype
• objects created using new use the prototype of the constructor function
• objects created using Object.create() have the prototype as the first parameter
• can query prototype using Object.getPrototypeOf()
• can use p.isPrototypeOf(q) to check if p in in prototype chain of q
• class
• type of object, no easy way to query
• typically get [object class] so need 8th to second-last character
• Object.prototype.toString.call(o).slice(8,-1) for object o
• just “object” if your own constructor, otherwise null, number, Boolean, array etc.
• Extensible
• whether new properties can be added
• check with Object.isExtensible()
• Object.preventExtensions() will permanently make it non-extensible
• Object.seal() will also make all properties nonconfigurable, check using Object.isSealed()
• Object.freeze() will also make all properties read-only, check using Object.isFrozen
Objects Manu Dube
Functions and Prototypes
• Every function in JavaScript has a prototype property
• created automatically when you define the function, initial value is empty object
• can add properties and methods to this object
• does not affect function
• useful if function is used as constructor
• objects created using constructor inherit prototype properties and methods
• if do not use new, returns undefined and creates properties of global object
<script>
function doNothing(){};
document.write(typeof doNothing.prototype);
<script>
function doNothing(){this.work="nothing"};
for(var i in doNothing.prototype)
var a = new doNothing();
document.write("<BR>"+i+doNothing.prototype[i]);
document.write(a.work+"<BR>");
document.write("hello");
var b = doNothing();
document.write(b+"<BR>");
doNothing.prototype.sing = function(){document.write("<BR>
document.write(work);
Hello World <BR>")};
</script>
var a = new doNothing();
a.sing();
</script>
Objects Manu Dube
Prototypes are Live
• All objects, including those created before modification, inherit changes
• unless you change prototype completely
<script>
function doNothing(){};
var a = new doNothing();
doNothing.prototype.sing = function(){document.write("<BR> Hello World <BR>")};
var b = new doNothing();
a.sing();
b.sing();
</script>
Objects Manu Dube
Prototypes, Objects and Properties
• Objects can have prototype chains
• if object has own property, that is accessed
• otherwise chain is searched
• the in operator shows if property is present, own or inherited
• hasOwnProperty method checks if property is in object
• propertyIsEnumerable checks if object has own property and it is enumerable
<script>
function doNothing(){};
doNothing.prototype.x = 15;
doNothing.prototype.y = 16;
var a = new doNothing();
a.x = 17;
document.write(a.x+" "+a.y);
if("x" in a) document.write("x is in a <BR>");
if("y" in a) document.write("y is in a <BR>");
if("z" in a) document.write("z is in a <BR>");
if(a.hasOwnProperty("x")) document.write("x own <BR>");
if(a.hasOwnProperty("y")) document.write("y own <BR>");
if(a.hasOwnProperty("z")) document.write("z own <BR>");
if(a.propertyIsEnumerable("x")) document.write("x is Enumerable <BR>");
if(a.propertyIsEnumerable("y")) document.write("y is Enumerable <BR>");
if(a.propertyIsEnumerable("z")) document.write("z is Enumerable <BR>");
</script>
Objects Manu Dube
Note
• Could add property to constructor directly or through its prototype …
<script>
function doNothing(a,b,c){
this.work=a,
this.urgent=b,
this.mustdo=c,
this.sing = function(){document.write("hello world");}
}
doNothing.prototype.shout=function(){document.write("HELLO WORLD");}
var useful = new doNothing("abc", "def", "ghi");
document.write(useful.hasOwnProperty("sing"));
document.write("<BR>");
document.write(useful.hasOwnProperty("shout"));
</script>
Objects Manu Dube
Constructor and Prototype
• Can check using instanceof operator to see which constructor was used
• Can use isPrototypeOf() to look up prototype in chain
• Can use getPrototypeOf() to get the prototype of the object
<script>
function doNothing(a,b,c){
this.work=a,
this.urgent=b,
this.mustdo=c
}
var useful = new doNothing("abc", "def", "ghi");
document.write(useful instanceof doNothing);
document.write("<BR>");
document.write(Object.prototype.isPrototypeOf(useful));
document.write("<BR>");
document.write(doNothing.prototype==Object.getPrototypeOf(useful));
document.write("<BR>");
document.write(Object.prototype==Object.getPrototypeOf(useful));
</script>
Objects Manu Dube
Inheritance
• Objects inherit properties from prototype, can override some
<script>
var Shape = {};
Shape.prototype = {
area: 0,
perimeter: 0,
print: function(){document.write(this.area+ " " + this.perimeter+"<BR>");}
}
var a = Object.create(Shape.prototype);
a.print();
var Rectangle = function(length, breadth){this.area = length*breadth; this.perimeter =
2*(length+breadth);}
Rectangle.prototype=Shape.prototype;
var b = new Rectangle(5,4);
b.print();
var Circle = function(radius){this.area=Math.PI*radius*radius; this.perimeter=2*Math.PI*radius;}
Circle.prototype=Shape.prototype;
var c = new Circle(5);
c.print();
</script>
Objects Manu Dube
Breaking the Reference
• Adding to the Rectangle prototype will change Shape prototype
• need to break the reference
<script>
var Shape = {};
Shape.prototype = {
area: 0,
perimeter: 0,
print: function(){document.write(this.area+ " " + this.perimeter+"<BR>");}
}
var Rectangle = function(len, brd){this.length = len; this.breadth= brd;}
var F = function(){}
F.prototype=Shape.prototype;
Rectangle.prototype=new F();
Rectangle.prototype.constuctor=Rectangle;
Rectangle.prototype.setArea=function(){this.area=this.length*this.breadth;}
Rectangle.prototype.setPerimeter=function(){this.perimeter=2*(this.length+this.breadth);}
var b = new Rectangle(5,4);
b.setArea();
b.setPerimeter();
b.print();
var Square=function(len){this.length=len; this.breadth=len;}
Square.prototype=Rectangle.prototype;
var a = new Square(3);
a.setArea();
a.setPerimeter();
a.print();
</script>
Objects Manu Dube
Serializing Objects
JavaScript Object Notation is JSON
•
JSON.stringify() to convert object's state to string
•
JSON.parse() to restore the object
•
Can be used for web services instead of SOAP
•
Look it up yourself!
•
Objects Manu Dube
Typical Common Object Methods
Objects inherit properties from Object.prototype, primarily methods
•
Universal methods, which can be customized, include
•
–toString()
–toLocaleString()
–toJSON
–valueOf()
Objects Manu Dube