Object-oriented and object-based
Almost every developer has development experience in object-oriented languages such as C + +, C #, Java. In traditional object-oriented languages, there are two very important concepts-classes and instances. A class defines a common behavior and method of a class of things, and an instance is a concrete implementation of a category. We also know that object-oriented programming has three important concepts-encapsulation, inheritance, and polymorphism.
But in the JavaScript world, none of these features seem to exist. Because JavaScript itself is not an object-oriented language, it is an object-based language. There are some interesting features here, such as everything in JavaScript is an object, including strings, arrays, dates, numbers, even functions, such as the following example:
Define a function-add
function Add (A, b) {
add.invoketimes++;
return a + B;
}
Because the function itself is also an object, here defines a property for the function add to record the number of times this function was invoked
Add.invoketimes = 0;
Add (1 + 1);
Add (2 + 3);
Console.log (add.invoketimes); 2
Simulate classes and inheritance in JavaScript
In object-oriented languages, we use classes to create a custom object. While everything in JavaScript is an object, what is the way to create a custom object?
This requires the introduction of another concept-prototype (prototype), we can simply think of prototype as a template, the newly created custom object is a copy of this template (prototype) (actually not a copy but a link, except that the link is not visible, It feels like a copy to the people.
Let's take a look at an example of creating a custom object through prototype:
Constructors
function person (name, sex) {
THIS.name = name;
This.sex = sex;
}
Defines the prototype of person, in which attributes can be referenced by custom objects
Person.prototype = {
Getname:function () {
return this.name;
},
Getsex:function () {
return this.sex;
}
}
Here we call the function person the constructor, which is the function that creates the custom object. As you can see, JavaScript simulates the functionality of a class by constructing functions and prototypes.
To create the code for the custom object (instantiated Class):
var Zhang = new person ("Zhangsan", "Mans");
Console.log (Zhang.getname ()); "Zhangsan"
var chun = new Person ("Chunhua", "Woman");
Console.log (Chun.getname ()); "Chunhua"
When the code var Zhang = new person ("Zhangsan" and "man") executes, there are actually several things internally:
- Creates a blank object (new Object ()).
- Copy attributes in Person.prototype (key-value pairs) into this empty object (as we mentioned earlier, the internal implementation is not a copy but a hidden link).
- Pass this object through the This keyword into the constructor and execute the constructor.
- Assign this object to the variable Zhang.
To prove that the prototype template is not copied to an instantiated object, but rather a way of linking, see the following code:
function person (name, sex) {
THIS.name = name;
This.sex = sex;
}
Person.prototype.age = 20;
var Zhang = new person ("Zhangsan", "Mans");
Console.log (zhang.age); 20
Overwrite the age attribute in prototype
Zhang.age = 19;
Console.log (zhang.age); 19
Delete Zhang.age;
This property value is then fetched from the prototype after the instance property age is deleted
Console.log (zhang.age); 20
This hidden prototype link, which is implemented in JavaScript, is the moist soil on which JavaScript relies, and also the basis for simulating inheritance.
How do I implement simple inheritance in JavaScript?
The following example creates an employee class employee that inherits all the attributes from the prototype prototype from person.
function Employee (name, sex, EmployeeID) {
THIS.name = name;
This.sex = sex;
This.employeeid = EmployeeID;
}
Point the employee's prototype to an instance of person
Because instances of person can invoke methods in the person prototype, instances of employee can also invoke all attributes in the person prototype.
Employee.prototype = new Person ();
Employee.prototype.getEmployeeID = function () {
return This.employeeid;
};
var Zhang = new Employee ("Zhangsan", "Man", "1234");
Console.log (Zhang.getname ()); "Zhangsan
The implementation of the above about inheritance is rough, and there are many problems:
- It is not appropriate to instantiate a person when creating an employee constructor and prototype (hereafter referred to as a class).
- The constructor of employee cannot invoke the constructor of the parent class person, causing a duplicate assignment of the name and sex properties in the employee constructor.
- Functions in employee overwrite functions with the same name in person, without mechanisms for overloading (and the previous one is a type of problem).
- The syntax for creating JavaScript classes is too fragmented to be as elegant as the syntax in C#/java.
- The implementation has a pointing error for the constructor attribute, which is discussed in the second article.
We will refine this example in Chapter three.
Implementation of JavaScript inheritance
Because JavaScript itself does not have a complete class and inheritance implementation, and we see a lot of problems with manual implementations, there are already many implementations of this challenging task online:
- Douglas Crockford- prototypal inheritance in JavaScript
- Douglas Crockford- classical inheritance in JavaScript
- John Resig-Simple JavaScript inheritance
- Dean Edwards- A Base Class for JavaScript inheritance
- Prototype
- Mootools
- Extjs
This series of articles will delve into these implementations in depth, culminating in an in-depth understanding of how to implement classes and inheritance in JavaScript.
In the next chapter we will introduce the relevant knowledge in the class implementation, such as this, constructor, prototype, etc.
In this chapter we will focus on several important attributes of JavaScript (this, constructor, prototype), which are essential to our understanding of how to implement classes and inheritance in JavaScript.
This
This represents the current object that refers to the current Page Object window if it is used globally, and if this is used in a function, this refers to what is invoked on the object based on this function at run time. We can also use apply and call two global methods to change the specific point of this in the function.
Let's look at an example of using this in a global scope:
<script type= "Text/javascript" >
console.log (this = = window);//True
console.log (Window.alert = = This.alert); True
Console.log (This.parseint ("021"));
</script>
The This in the function is determined at run time, not when the function is defined, as follows:
Defines a global function functions
foo () {
console.log (this.fruit);
}
Defines a global variable, equivalent to Window.fruit = "Apple";
var fruit = "Apple";
This point in the function Foo points to the Window object
//This invocation and Window.foo (); is exactly equivalent
foo ();///"Apple"/
custom object, And point the object's property foo to the global function foo
var pack = {
fruit: "Orange",
Foo:foo
};
This point in function foo points to the Window.pack object
pack.foo ();//"Orange"
Global functions apply and call can be used to change the direction of this in a function, as follows:
Defines a global function functions
foo () {
console.log (this.fruit);
}
Define a global variable
var fruit = "Apple";
Customize an object
var pack = {
fruit: "Orange"
};
Equivalent to Window.foo ();
foo.apply (window); "Apple"/
this time in Foo's this = = Pack
foo.apply (Pack);//"Orange"
Note: Apply and call two functions have the same function, the only difference is that the parameters of the two functions are defined differently.
Because functions are also objects in JavaScript, we can see the following interesting examples:
Defines a global function functions
foo () {
if (this = = window) {
Console.log ("This is window.");
}
function Foo is also an object, so you can define the property boo for Foo as a function
Foo.boo = functions () {
if (this = = foo) {
Console.log (' This is foo. ');
else if (this = = window) {
Console.log ("This is window.");
}
;
Equivalent to Window.foo ();
Foo (); This is window.
You can see the object Foo.boo () of this in the function pointing to the calling function
;//is foo.
Use apply to change this in the function to point to
foo.boo.apply (window);//this is window.
Prototype
We have used prototype to simulate class and inheritance implementations in chapter one. Prototype is essentially a JavaScript object. And each function has a default prototype property.
If this function is used in a scene that creates a custom object, we call this function a constructor. For example, here's a simple scenario:
constructor function person
(name) {
this.name = name;
}
Defines the prototype of person, in which attributes can be referenced by custom objects
Person.prototype = {
getname:function () {return
this.name;
}
}
var Zhang = new person ("Zhangsan");
Console.log (Zhang.getname ()); "Zhangsan"
As an analogy, consider the data types in JavaScript-strings, numbers, arrays (array), objects (object), dates (date), and so on. We have reason to believe that these types are implemented as constructors within JavaScript, such as:
Defines the constructor of an array as a predefined type
function array () {
//...
}
of JavaScript. Initializes an instance of an array
var arr1 = new Array (1,%,);
However, we prefer the following syntax definition:
var arr2 = [1, 56, 34, 12];
Many of the methods (such as Concat, join, push) of an array operation should also be defined in the prototype attribute.
In fact, all of the intrinsic data types of JavaScript have read-only prototype attributes (this is understandable: because if these types of prototype properties are modified, which predefined methods disappear), we can add our own extension methods to them.
Extend a method to get the minimum value to the JavaScript intrinsic type Array
Array.prototype.min = function () {
var min = this[0];
for (var i = 1; i < this.length i++) {
if (This[i] < min) {
min = this[i];
}
}
return min;
};
Call the Min method on an instance of any array
([1, Console.log, 12].min ());/1
Note: There is a trap to add an extension method to the array's prototype, and the extension method is also recycled when the for-in loop array is used.
The following code illustrates this (assuming that the Min method has been extended to the array's prototype):
var arr = [1,%, n];
var total = 0;
for (var i in arr) {Total
= parseint (Arr[i];
}
Console.log (total); NaN
The solution is also simple:
var arr = [1,%, n];
var total = 0;
for (var i in arr) {
if (Arr.hasownproperty (i)) {total
+ = parseint (Arr[i], ten)
;
}
Console.log (total); 103
Constructor
Constructor always points to the constructor that creates the current object. For example, the following example:
Equivalent to var foo = new Array (1,%,);
var arr = [1,%, n];
Console.log (Arr.constructor = = Array); True
//equivalent to var foo = new Function ();
var Foo = function () {};
Console.log (Foo.constructor = = Function); True
//The constructor instantiates an obj object
var obj = new Foo ();
Console.log (Obj.constructor = = = Foo); True
//combine the above two pieces of code to get the following conclusion
console.log (Obj.constructor.constructor = = Function);//True
But when constructor met prototype, something interesting happened.
We know that each function has a default attribute prototype, and this prototype constructor the default point to this function. As shown in the following example:
function person (name) {
this.name = name;
};
Person.prototype.getName = function () {return
this.name;
};
var p = new Person ("Zhangsan");
Console.log (P.constructor = = person); True
console.log (Person.prototype.constructor = = person);//True
//merge The last two lines of code to get the following result
Console.log ( P.constructor.prototype.constructor = = person); True
When we redefined the prototype of a function (note: The difference between this and the previous example is not a modification but a overwrite), constructor's behavior is a bit strange, as follows:
function person (name) {
this.name = name;
};
Person.prototype = {
getname:function () {return
this.name;
}
};
var p = new Person ("Zhangsan");
Console.log (P.constructor = = person); False
console.log (Person.prototype.constructor = = person);//False
Console.log ( P.constructor.prototype.constructor = = person); False
Why, then?
It turns out that overwriting person.prototype is equivalent to doing the following code:
Person.prototype = new Object ({
getname:function () {return
this.name;
}
});
and constructor always point to the constructor that created itself, so Person.prototype.constructor = = = Object At this point, that is:
function person (name) {
this.name = name;
};
Person.prototype = {
getname:function () {return
this.name;
}
};
var p = new Person ("Zhangsan");
Console.log (P.constructor = = = Object); True
console.log (Person.prototype.constructor = = = Object);//True
Console.log ( P.constructor.prototype.constructor = = = Object); True
How to fix this problem? The method is also very simple, the Person.prototype.constructor can be overwritten again:
function person (name) {
this.name = name;
};
Person.prototype = new Object ({
getname:function () {return
this.name;
}
});
Person.prototype.constructor = person;
var p = new Person ("Zhangsan");
Console.log (P.constructor = = person); True
console.log (Person.prototype.constructor = = person);//True
Console.log ( P.constructor.prototype.constructor = = person); True
In the next chapter, we will improve the implementation of the Person-employee class and inheritance mentioned in the first chapter.
Posted @ 2009-07-08 16:30 Sansheng Stone reading (512) | Comments (1) | Edit
JavaScript inheritance detailed (i)
Object-oriented and object-based
Almost every developer has development experience in object-oriented languages such as C + +, C #, Java. In traditional object-oriented languages, there are two very important concepts-classes and instances. A class defines a common behavior and method of a class of things, and an instance is a concrete implementation of a category. We also know that object-oriented programming has three important concepts-encapsulation, inheritance, and polymorphism.
But in the JavaScript world, none of these features seem to exist. Because JavaScript itself is not an object-oriented language, it is an object-based language. There are some interesting features here, such as everything in JavaScript is an object, including strings, arrays, dates, numbers, even functions, such as the following example:
Define a function-add
function Add (A, b) {
add.invoketimes++;
return a + B;
}
Because the function itself is also an object, here defines a property for the function add to record the number of times this function was invoked
Add.invoketimes = 0;
Add (1 + 1);
Add (2 + 3);
Console.log (Add.invoketimes); 2
Simulate classes and inheritance in JavaScript
In object-oriented languages, we use classes to create a custom object. While everything in JavaScript is an object, what is the way to create a custom object?
This requires the introduction of another concept-prototype (prototype), we can simply think of prototype as a template, the newly created custom object is a copy of this template (prototype) (actually not a copy but a link, except that the link is not visible, It feels like a copy to the people.
Let's take a look at an example of creating a custom object through prototype:
Constructors
function person (name, sex) {
THIS.name = name;
This.sex = sex;
}
Defines the prototype of person, in which attributes can be referenced by custom objects
Person.prototype = {
Getname:function () {
return this.name;
},
Getsex:function () {
return this.sex;
}
}
Here we call the function person the constructor, which is the function that creates the custom object. As you can see, JavaScript simulates the functionality of a class by constructing functions and prototypes.
To create the code for the custom object (instantiated Class):
var Zhang = new person ("Zhangsan", "Mans");
Console.log (Zhang.getname ()); "Zhangsan"
var chun = new Person ("Chunhua", "Woman");
Console.log (Chun.getname ()); "Chunhua"
When the code var Zhang = new person ("Zhangsan" and "man") executes, there are actually several things internally:
- Creates a blank object (new Object ()).
- Copy attributes in Person.prototype (key-value pairs) into this empty object (as we mentioned earlier, the internal implementation is not a copy but a hidden link).
- Pass this object through the This keyword into the constructor and execute the constructor.
- Assign this object to the variable Zhang.
To prove that the prototype template is not copied to an instantiated object, but rather a way of linking, see the following code:
function person (name, sex) {
THIS.name = name;
This.sex = sex;
}
Person.prototype.age = 20;
var Zhang = new person ("Zhangsan", "Mans");
Console.log (Zhang.age); 20
Overwrite the age attribute in prototype
Zhang.age = 19;
Console.log (Zhang.age); 19
Delete Zhang.age;
This property value is then fetched from the prototype after the instance property age is deleted
Console.log (Zhang.age); 20
This hidden prototype link, which is implemented in JavaScript, is the moist soil on which JavaScript relies, and also the basis for simulating inheritance.
How do I implement simple inheritance in JavaScript?
The following example creates an employee class employee that inherits all the attributes from the prototype prototype from person.
function Employee (name, sex, EmployeeID) {
THIS.name = name;
This.sex = sex;
This.employeeid = EmployeeID;
}
Point the employee's prototype to an instance of person
Because instances of person can invoke methods in the person prototype, instances of employee can also invoke all attributes in the person prototype.
Employee.prototype = new Person ();
Employee.prototype.getEmployeeID = function () {
return This.employeeid;
};
var Zhang = new Employee ("Zhangsan", "Man", "1234");
Console.log (Zhang.getname ()); "Zhangsan
The implementation of the above about inheritance is rough, and there are many problems:
- It is not appropriate to instantiate a person when creating an employee constructor and prototype (hereafter referred to as a class).
- The constructor of employee cannot invoke the constructor of the parent class person, causing a duplicate assignment of the name and sex properties in the employee constructor.
- Functions in employee overwrite functions with the same name in person, without mechanisms for overloading (and the previous one is a type of problem).
- The syntax for creating JavaScript classes is too fragmented to be as elegant as the syntax in C#/java.
- The implementation has a pointing error for the constructor attribute, which is discussed in the second article.
We will refine this example in Chapter three.