Two days ago I had a former co-worker who was always asking me JavaScript object-oriented stuff, so just write an article to let him see it, this article mainly wants to explain the JavaScript object-oriented programming from a whole point of view. (written in haste, there should be inaccurate or wrong place, please criticize)
In addition, this article is mainly based on ECMAScript 5, which aims to introduce new technologies. For compatibility, see the last section.
Of
We know that the definition of variables in JavaScript is basically as follows:
Copy Code code as follows:
var name = ' Chen Hao ';;
var email = ' Haoel (@) hotmail.com ';
var website = ' Http://jb51.net ';
If you want to write with the object, this is the following:
Copy Code code as follows:
var Chenhao = {
Name: ' Chen Hao ',
Email: ' Haoel (@) hotmail.com ',
Website: ' Http://jb51.net '
};
So I can access it like this:
Copy Code code as follows:
In the way of members
Chenhao.name;
Chenhao.email;
Chenhao.website;
In the way of hash map
chenhao["Name"];
chenhao["email"];
chenhao["website"];
With regard to functions, we know that JavaScript functions are like this:
Copy Code code as follows:
var dosomething = function () {
Alert (' Hello world. ');
};
So, we can do this:
Copy Code code as follows:
var SayHello = function () {
var hello = "Hello, I ' m" + this.name
+ ", my email is:" + this.email
+ ", my website is:" + this.website;
alert (hello);
};
Direct assignment, this is very much like C + + 's function pointer
Chenhao. Hello = SayHello;
Chenhao. Hello ();
Believe that these things are relatively simple, we all understand. You can see that JavaScript object functions are directly declared, directly assigned, and used directly. The dynamic language of the runtime.
There is also a comparative specification of the following:
Copy Code code as follows:
We can see that it uses function to do class.
var person = function (name, email, website) {
THIS.name = name;
This.email = email;
This.website = website;
This.sayhello = function () {
var hello = "Hello, I ' m" + this.name + ", \ n" +
"My email is:" + this.email + "\ n" +
"My website is:" + this.website;
alert (hello);
};
};
var Chenhao = new Person ("Chen Hao", "haoel@hotmail.com",
"Http://jb51.net");
Chenhao.sayhello ();
By the way, to delete an object's properties, it's simple:
1 Delete chenhao[' email ']
These examples above, we can see a few of these:
JavaScript data and member encapsulation is simple. No class is entirely an object operation. Pure dynamic!
The this pointer in a Javascript function is critical, and if not, it is a local variable or a local function.
JavaScript Object member functions can be declared temporarily when used, and a global function is directly assigned to the past.
A member function of JavaScript can be modified on an instance, meaning that the behavior of the same function name for different instances is not necessarily the same.
Property Configuration –object.defineproperty
First look at the following code:
Copy Code code as follows:
Creating objects
var Chenhao = object.create (null);
Set a property
Object.defineproperty (Chenhao,
' Name ', {value: ' Chen Hao ',
Writable:true,
Configurable:true,
Enumerable:true});
Set multiple properties
Object.defineproperties (Chenhao,
{
' Email ': {value: ' haoel@hotmail.com ',
Writable:true,
Configurable:true,
Enumerable:true},
' website ': {value: ' Http://jb51.net ',
Writable:true,
Configurable:true,
Enumerable:true}
}
);
Let's say what these attribute configurations mean.
Writable: Whether the value of this property can be changed.
Configurable: Whether the configuration of this property can be changed.
Enumerable: Whether this attribute can be traversed in the for...in loop or enumerated in the Object.keys.
Value: Property values.
Get ()/set (_value): Get and set accessors.
Get/set accessor
With regard to the get/set accessor, it means to replace value with a get/set (which cannot be used with value), as shown in the following example:
Copy Code code as follows:
var age = 0;
Object.defineproperty (Chenhao,
' Age ', {
Get:function () {return age+1;},
Set:function (value) {age = value;}
Enumerable:true,
Configurable:true
}
);
Chenhao.age = 100; Call Set
alert (chenhao.age); Call Get Output (+ 1 in Get);
Let's look at a more practical example--using an existing property (age) to construct a new property (Birth_year) through get and set:
Copy Code code as follows:
Object.defineproperty (Chenhao,
' Birth_year ',
{
Get:function () {
var d = new Date ();
var y = d.getfullyear ();
return (Y-this.age);
},
Set:function (year) {
var d = new Date ();
var y = d.getfullyear ();
This.age = Y-year;
}
}
);
alert (chenhao.birth_year);
Chenhao.birth_year = 2000;
alert (chenhao.age);
This seems to be a bit of a hassle, and you say, why don't I write the following:
Copy Code code as follows:
var Chenhao = {
Name: "Chen Hao",
Email: "Haoel@hotmail.com",
Website: "Http://jb51.net",
AGE:100,
Get Birth_year () {
var d = new Date ();
var y = d.getfullyear ();
return (Y-this.age);
},
Set Birth_year (year) {
var d = new Date ();
var y = d.getfullyear ();
This.age = Y-year;
}
};
alert (chenhao.birth_year);
Chenhao.birth_year = 2000;
alert (chenhao.age);
Yes, you can do that, but through DefineProperty () You can do these things:
1 Set the property configuration such as Writable,configurable,enumerable.
2) dynamically adding attributes to an object. For example: Some HTML DOM for the image.
View object property Configuration
If you view and manage these configurations for an object, there is a program that can output objects such as properties and configurations:
Copy Code code as follows:
Lists the properties of the object.
function listproperties (obj)
{
var newline = "<br/>";
var names = Object.getownpropertynames (obj);
for (var i = 0; i < names.length; i++) {
var prop = Names[i];
document.write (prop + newline);
Lists the object's property configuration (descriptor) using the Getownpropertydescriptor function.
var descriptor = Object.getownpropertydescriptor (obj, prop);
for (var attr in descriptor) {
document.write ("..." + attr + ': ' + descriptor[attr]);
document.write (newline);
}
document.write (newline);
}
}
Listproperties (Chenhao);
Call,apply, bind and this
The this pointer about JavaScript is similar to C++/java. Let's take a look at an example: (This example is very simple, I will not say more)
Copy Code code as follows:
function print (text) {
document.write (This.value + '-' + text+ ' <br> ');
}
var a = {value:10, print:print};
var B = {value:20, print:print};
Print (' hello ');/This => global, output "Undefined-hello"
A.print (' a ');/This => A, output "10-a"
B.print (' B '); This => B, output "20-b"
a[' print '] (' a '); This => A, output "10-a"
Let's take a look at call and apply, the difference between the two functions is that the parameters look different, the other is the performance is not the same, apply performance is much worse. (about performance, can go to Jsperf to run and see)
Copy Code code as follows:
Print.call (A, ' a '); This => A, output "10-a"
Print.call (b, ' B '); This => B, output "20-b"
Print.apply (A, [' a ']); This => A, output "10-a"
Print.apply (b, [' B ']); This => B, output "20-b"
But after bind, the this pointer may be different, but because JavaScript is dynamic. As the following example
Copy Code code as follows:
var p = print.bind (a);
P (' a '); This => A, output "10-a"
P.call (b, ' B '); This => A, output "10-b"
P.apply (b, [' B ']); This => A, output "10-b"
Inheritance and overloading
With those examples above, we can actually inherit by Object.create (), see the code below, student inherits from object.
Copy Code code as follows:
var person = object.create (null);
Object.defineproperties
(
Person,
{
' name ': {value: ' Chen Hao '},
' Email ': {value: ' haoel@hotmail.com '},
' website ': {value: ' Http://jb51.net '}
}
);
Person.sayhello = function () {
var hello = "<p>hello, I am" + this.name + ", <br>" +
"My email is:" + This.email + ", <br>" +
"My website is:" + this.website;
document.write (hello + "<br>");
}
var Student = object.create (person);
student.no = "1234567"; School Number
Student.dept = "Computer science"; System
Using the property of person
document.write (student.name + ' + student.email + ' + student.website + ' <br> ');
Ways to use person
Student.sayhello ();
Overloaded SayHello method
Student.sayhello = function (person) {
var hello = "<p>hello, I am" + this.name + ", <br>" +
"My email is:" + This.email + ", <br>" +
"My website are:" + this.website + "<br>" +
' My student No: ' + this. No + ", <br>" +
"My departent are:" + this. Dept
document.write (hello + ' <br> ');
}
Call again
Student.sayhello ();
View Student properties (only the No, dept, and overloaded SayHello)
document.write (' <p> ' + object.keys (Student) + ' <br> ');
The generic example above, we can see that the attribute in person is not actually copied into the student, but we can access it. This is because JavaScript implements this mechanism with delegates. In fact, this is Prototype,person is student prototype.
When our code needs a property, the JavaScript engine first looks at the current object for this attribute, and if not, finds out if the prototype object has this attribute and continues until it finds or until there is no prototype object.
To prove this, we can use Object.getprototypeof () to test:
Copy Code code as follows:
Student.name = ' AAA ';
Output AAA
document.write (' <p> ' + student.name + ' </p> ');
Output Chen Hao
document.write (' <p> ' +object.getprototypeof (Student). Name + ' </p> ');
So, you can also call the parent object's function in the function of the child object, just like Base::func () in C + +. So we can overload the Hello method with the code of the parent class, as follows:
Copy Code code as follows:
New version of the overloaded SayHello method
Student.sayhello = function (person) {
Object.getprototypeof (This). Sayhello.call (this);
var Hello = "My student No are:" + this. No + ", <br>" +
"My departent are:" + this. Dept
document.write (hello + ' <br> ');
}
This is very powerful.
Combination
The above is not enough to meet our requirements, and we may want these objects to be truly combined. Why do you want to mix? Because we all know that this is the most important thing in oo design. However, this is not very good for JavaScript, and we can still get things done.
First, we need to define a composition function: (Target is the object, source is the original object), the following code is very simple, that is, the property in source is taken out and then defined into target.
Copy Code code as follows:
function composition (target, source)
{
var desc = object.getownpropertydescriptor;
var prop = Object.getownpropertynames;
var def_prop = Object.defineproperty;
Prop (source). ForEach (
function (key) {
Def_prop (target, key, desc (source, key))
}
)
return target;
}
With this function, we can play with this:
Copy Code code as follows:
Artist
var Artist = object.create (null);
artist.sing = function () {
Return THIS.name + ' starts singing ... ';
}
Artist.paint = function () {
Return this.name + ' starts painting ... ';
}
Athletes
var sporter = object.create (null);
Sporter.run = function () {
Return THIS.name + ' starts running ... ';
}
Sporter.swim = function () {
Return this.name + ' starts swimming ... ';
}
Composition (person, Artist);
document.write (person.sing () + ' <br> ');
document.write (Person.paint () + ' <br> ');
Composition (person, sporter);
document.write (Person.run () + ' <br> ');
document.write (Person.swim () + ' <br> ');
See what's in person? (Output: Sayhello,sing,paint,swim,run)
document.write (' <p> ' + object.keys (person) + ' <br> ');
Prototype and inheritance
Let's talk about prototype first. Let's take a look at the following routines, this routine doesn't need to be explained, much like a function pointer in C, which is so much more in C language.
Copy Code code as follows:
var plus = function (x,y) {
document.write (x + ' + ' + y + ' = ' + (x+y) + ' <br> ');
return x + y;
};
var minus = function (x,y) {
document.write (x + '-' + y + ' = ' + (XY) + ' <br> ');
return x-y;
};
var operations = {
' + ': Plus,
'-': minus
};
var calculate = function (x, y, operation) {
return operations[operation] (x, y);
};
Calculate (12, 4, ' + ');
Calculate (24, 3, '-');
So, can we wrap these things up and we need to use prototype. Look at the following example:
Copy Code code as follows:
var Cal = function (x, y) {
this.x = x;
This.y = y;
}
Cal.prototype.operations = {
' + ': function (x, y) {return x+y;},
'-': function (x, y) {return xy;}
};
Cal.prototype.calculate = function (operation) {
return this.operations[operation] (this.x, THIS.Y);
};
var c = new Cal (4, 5);
C.calculate (' + ');
C.calculate ('-');
This is the use of prototype, prototype is the most important content in the language of JavaScript. There are too many articles on the Internet to start this thing. To be blunt, prototype is an extension of an object, characterized by a "copy" of an existing instance to return a new instance, rather than a new instance. The replicated instance is what we call "prototypes", and this prototype is customizable (of course, there's no real replication, actually just a delegate). In the example above, we extended the instance Cal to have a operations attribute and a calculate method.
In this way, we can implement inheritance through this feature. Remember the person in front of us, and the following example is to create a student to inherit someone.
Copy Code code as follows:
function person (name, email, website) {
THIS.name = name;
This.email = email;
This.website = website;
};
Person.prototype.sayHello = function () {
var hello = "Hello, I am" + this.name + ", <br>" +
"My email is:" + This.email + ", <br>" +
"My website is:" + this.website;
return hello;
};
function Student (name, email, website, no, dept) {
var proto = object.getprototypeof;
Proto (Student.prototype). Constructor.call (this, name, email, website);
this.no = no;
this.dept = Dept;
}
Inherit prototype
Student.prototype = Object.create (Person.prototype);
Resetting constructors
Student.prototype.constructor = Student;
Overloaded SayHello ()
Student.prototype.sayHello = function () {
var proto = object.getprototypeof;
var hello = Proto (Student.prototype). Sayhello.call (This) + ' <br> ';
Hello + = "My student No is:" + this. No + ", <br>" +
"My departent are:" + this. Dept
return hello;
};
var me = new Student (
"Chen Hao",
"Haoel@hotmail.com",
"Http://jb51.net",
"12345678",
"Computer Science"
);
document.write (Me.sayhello ());
Compatibility
The above code does not necessarily work in all browsers, because the above code follows the ECMAScript 5 specification, ECMAScript 5 browser Compatibility List, you can see here "ES5 Browser compatibility table."
All the code in this article has been tested in the latest version of Chrome.
Here are some functions that you can use in browsers that are not compatible with ES5:
Object.create () function
Copy Code code as follows:
function Clone (proto) {
function Dummy () {}
Dummy.prototype = Proto;
Dummy.prototype.constructor = Dummy;
return new Dummy (); Equivalent to object.create (person);
}
var me = clone (person);
DefineProperty () function
Copy Code code as follows:
function DefineProperty (target, key, descriptor) {
if (Descriptor.value) {
Target[key] = Descriptor.value;
}else {
Descriptor.get && target.__definegetter__ (key, Descriptor.get);
Descriptor.set && target.__definesetter__ (key, Descriptor.set);
}
return target
}
Keys () function
Copy Code code as follows:
function keys (object) {var result, key
result = [];
For (key in object) {
if (Object.hasownproperty (key)) Result.push (key)
}
return result;
}
Object.getprototypeof () function
Copy Code code as follows:
function Proto (object) {
Return!object? Null
: ' __proto__ ' in object? object.__proto__
:/* not exposed? * * Object.constructor.prototype
}
Bind function
Copy Code code as follows:
var slice = [].slice
function bind (FN, bound_this) {var Bound_args
Bound_args = Slice.call (arguments, 2)
return function () {var args
args = Bound_args.concat (slice.call (arguments))
Return fn.apply (Bound_this, args)}
}
Reference
W3cschool
MDN (Mozilla Developer Network)
MSDN (Microsoft Software Development Network)
Understanding Javascript OOP.