Home > Web Front-end > JS Tutorial > Javascript object-oriented features_javascript skills

Javascript object-oriented features_javascript skills

WBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWB
Release: 2016-05-16 18:37:57
Original
1056 people have browsed it

1. Types in JavaScript
--------
Although JavaScript is an object-based language, objects (Object) are not the first type in JavaScript. JS
is a language with Function as the first type. This is not only because functions in JS have various characteristics of functions in high-level languages, but also because in JS, Object is also implemented by functions. ——On this point, you can see further explanation in the "Construction and Destruction" section of
.

JS is weakly typed, and its built-in types are simple and clear:
-------------------------- -------------------------------
undefined : Undefined
number : Number
boolean : Boolean value
string: string
function: function
object: object

1). undefined type
================ ========
In IE5 and below, except for direct assignment and typeof(), any other operation on undefined will cause a
exception. If you need to know whether a variable is undefined, you can only use the typeof() method:



But in IE5.5 and above, undefined is an implemented system reserved word. Therefore, undefined can be used for
comparison and operation. A simpler way to check if a value is undefined could be:



So in order to make the core code (partially) compatible with IE5 and earlier versions, there is a line of code in the Romo core unit to
"Declare" an undefined value:
//---------------------------------- -----------------------
// code from Qomolangma, in JSEnhance.js
//---------- -----------------------------------------------
var undefined = void null;

There is another point that needs to be explained in this line of code, which is the application of void statement. void means "execute the following statements and
ignore the return value". Therefore any "single" statement that can be executed can appear after void. The result of execution is <script> <BR>var v; <BR>if (typeof(v) == 'undefined') { <BR>// ... <BR>} <BR></script>undefined. Of course, if you want, you can also "define undefined" with one of the codes below.
//--------------------------------------------- ------------
// 1. A more complex method, using an anonymous empty function to return
//------------ ---------------------------------------------
var undefined = function(){}();

//--------------------------------- --------------------------
// 2. The code is simpler, but not easy to understand
//----- -------------------------------------------------- --
var undefined = void 0;

void can also be used like a function, so void(0) is also legal. Sometimes, some complex statements may not be able to use the void keyword form
, but must use the void function form. For example:
//------------------------------------------------ ----------------
// Complex expressions in the form of void() must be used
//---------------- ----------------------------------------
void(i=1) ; // Or the following statement:
void(i=1, i );

2). number type
================== =======
JavaScript always deals with floating point numbers, so it does not have constants like MaxInt in Delphi. Instead, it has two constant value definitions like these
:
Number.MAX_VALUE : Returns the largest number that JScript can express. Approximately equal to 1.79E 308.
Number.MIN_VALUE: Returns the number closest to 0 in JScript. Approximately equal to 2.22E-308.

Because there is no integer type, in some operations on CSS and DOM properties, if you expect the value to be an integer 2,
you may get the string "2.0" - or similar Some situations in this regard. In this case, you may need to use
to the parseInt() method of the global object (Gobal).

There are two properties in the global object (Gobal) related to number type operations:
NaN: If the result of an arithmetic expression is not a number, a NaN value is returned.
Infinity: A number greater than MAX_VALUE.

If a value is NaN, then it can be detected through the isNaN() method of the global object (Gobal). However, two NaN
values ​​are not equal to each other. As an example:
//------------------------------------------------ ---------------
//NaN operation and detection
//-------------------- -------------------------------------
var
v1 = 10 * 'a ';
v2 = 10 * 'a';
document.writeln(isNaN(v1));
document.writeln(isNaN(v2));
document.writeln(v1 == v2 );

The Infinity of the global object (Gobal) represents a value greater than the largest number (Number.MAX_VALUE). In JS,
has the same value as positive infinity in mathematical operations. ——In some practical techniques, it can also be used to do boundary detection of an
array sequence.

Infinity is defined as POSITIVE_INFINITY in the Number object. In addition, negative infinity is also defined in Number:
Number.POSITIVE_INFINITY: A value greater than the largest positive number (Number.MAX_VALUE). Positive infinity.
Number.NEGATIVE_INFINITY : A value smaller than the smallest negative number (-Number.MAX_VALUE). Negative infinity.

Different from NaN, two Infinity (or -Infinity) are equal to each other. As an example:
//------------------------------------------------ ---------------
//Infinity operation and detection
//-------------------- -------------------------------------
var
v1 = Number.MAX_VALUE * 2;
v2 = Number.MAX_VALUE * 3;
document.writeln(v1);
document.writeln(v2);
document.writeln(v1 == v2);

Other methods related to the number type in Global are:
isFinite(): If the value is NaN/positive infinity/negative infinity, return false, otherwise return true.
parseFloat(): Take a floating point number from (the prefix part of the string). If unsuccessful, NaN is returned.

3). boolean type
========================
(omitted)

4). string type
========================
The String type in JavaScript is originally nothing special, but in order to adapt to
"Browser-implemented hypertext environment", so it has some weird methods. For example:
link(): Place a hyperlink tag
with HREF attribute at both ends of the text in the String object. big(): Place a pair of
tags at both ends of the text in the String object. The following methods are similar to this:
anchor()
blink()
bold()
fixed()
fontcolor()
fontsize()
italics ()
small()
strike()
sub()
sup()

Beyond that, the main complexity of string comes from the ubiquity of toString in JavaScript ()
method. This is also a very important method provided by JavaScript for the browser environment.For example, if we
declare an object, but use document.writeln() to output it, what will be displayed in IE?

The following example illustrates this problem:
//--------------------------------- --------------------------
//Application of toString()
//---------- -----------------------------------------------
var
s = new Object();

s.v1 = 'hi,';
s.v2 = 'test!';
document.writeln(s);
document.writeln(s.toString());

s.toString = function() {
return s.v1 s.v2;
}
document.writeln(s);

In this example, we see that when an object does not redeclare (override) its own toString() method
, then it is used as a string type (for example, by writeln) , the default toString() of the Java Script
environment will be called. In turn, you can redefine the way JavaScript understands this object
.

Many JavaScript frameworks take advantage of this feature when implementing the "template" mechanism. For example
they define a FontElement object like this:
//--------------------------------- --------------------------
// The simple principle of using toString() to implement the template mechanism
//------ -------------------------------------------------- -
function FontElement(innerHTML) {
this.face = '宋体';
this.color = 'red';
// more...

var ctx = innerHTML;
this.toString = function() {
return ''
ctx
'
';
}
}

var obj = new FontElement('This is a test.');

// Pay attention to the writing of the following line of code
document.writeln(obj);

5). function type
========================
Javascript functions have many features, in addition to the object-oriented part (this will be described later), Some of its own unique features are also widely used.

First of all, every function in JavaScript can have an arguments object during the calling process. This
object is created by the script interpretation environment, you have no other way to create an arguments object yourself.

arguments can be regarded as an array: it has a length attribute, and each parameter can be accessed through arguments[n]
. However, the most important thing is that you can get a reference to the function object that is executing
through the callee attribute.

The next question becomes interesting: the Function object has a caller attribute, which points to a reference to the parent function object that is calling the current
function.

- We have seen that we can traverse the call stack of the
period through callee/caller in JavaScript. Since arguments is actually an attribute of Function, we can actually
traverse the parameters of each function on the execution call stack. The code below is a simple example:

//--------------------------------- ---------------------
//Traversal of the call stack
//--------------------- ------------------------------------------------
function foo1 (v1, v2) {
foo2(v1 * 100);
}

function foo2(v1) {
foo3(v1 * 200);
}

function foo3(v1) {
var foo = arguments.callee;
while (foo && (foo != window)) {
document.writeln('Call parameters:
', ' ---------------
');

var args = foo.arguments, argn = args.length;
for (var i=0; idocument.writeln('args[', i, ']: ', args[i], '');
}
document.writeln('
');

// Previous level
foo = foo.caller;
}
}

// Run test
foo1(1 , 2);

2. JavaScript object-oriented support
--------
In the previous example, we have actually talked about the "type declaration" and "instance" of the object type create".
In JavaScript, we need to declare our object type through a function:
//-------------------------- -------------------------------
//Formal code for object type declaration in JavaScript
// (In future documents, "object name" is usually replaced by MyObject)
//-------------------------------- ----------------------------
function object name (parameter list) {
this.property = initial value;

this.method = function (method parameter list) {
//Method implementation code
}
}

Then, we can create this object through code like this An instance of type:
//------------------------------------------------ ------------------
//Formal code for creating an instance
// (In future documents, "instance variable name" is usually replaced by obj)
//--------------------------------------------- -----------
var instance variable name = new object name (parameter list);

Next let's look at some specific implementations and strangenesses of "objects" in JavaScript characteristic.

1). The five-fold identity of functions in JavaScript’s object-oriented mechanism
------
“Object name”—such as MyObject()—this function serves as the following Language roles:
(1) Ordinary function
(2) Type declaration
(3) Type implementation
(4) Class reference
(5) Object constructor

Some programmers (e.g. Delphi programmers) are used to keeping type declarations separate from implementation. For example, in delphi
, the Interface section is used to declare types or variables, while the implementation section is used to write the implementation code of the type
, or some functions and code processes for execution.

But in JavaScript, type declaration and implementation are mixed together. The type (class) of an object
is declared through a function, and this.xxxx indicates the attributes or methods that the object can have.

This function is also a "class reference". In JavaScript, if you need to identify the specific type of an object
, you need to hold a "class reference". ——Of course, this is the name of this function
. The instanceof operator is used to identify the type of instance. Let’s take a look at its application:
//-------------------------- ----------------------------------
// Type identification of objects in JavaScript
// Syntax: Object Instance instanceof class reference
//----------------------------------------- ----------------
function MyObject() {
this.data = 'test data';
}

// MyObject here () is used as a constructor
var obj = new MyObject();
var arr = new Array();

// Here MyObject is used as a class reference
document.writeln(obj instanceof MyObject);
document.writeln(arr instanceof MyObject);

================
(To be continued)
= ===============
Next content:

2. JavaScript object-oriented support
--------

2). Implementation of reflection mechanism in JavaScript
3). Use of this and with keywords
4). Operations using the in keyword
5). Operations using the instanceof keyword
6). Other object-oriented keywords

3. Construction and destruction

4. Instances and instance references

5. Prototype issues

6. Function context

7. Object type checking issues

2). Implementation of reflection mechanism in JavaScript
------
The reflection mechanism is implemented in JavaScript through the for..in syntax. However, JavaScript does not
clearly distinguish between "properties", "methods", and "events". Therefore, type checking properties is a problem in JS
. The following code is a simple example of the use of for..in and attribute identification:
//----------------------------- -----------------------------
// The use and attribute identification of for..in in JavaScript
//-- -------------------------------------------------- -----
var _r_event = _r_event = /^[Oo]n.*/;
var colorSetting = {
method: 'red',
event: 'blue',
property: ''
}

var obj2 = {
a_method : function() {},
a_property: 1,
onclick: undefined
}

function propertyKind(obj, p) {
return (_r_event.test(p) && (obj[p]==undefined || typeof(obj[p])=='function')) ? 'event '
: (typeof(obj[p])=='function') ? 'method'
: 'property';
}

var objectArr = ['window', ' obj2'];

for (var i=0; idocument.writeln('

for ', objectArr[i], '


' );

var obj = eval(objectArr[i]);
for (var p in obj) {
var kind = propertyKind(obj, p);
document.writeln( 'obj.', p, ' is a ', kind.fontcolor(colorSetting[kind]), ': ', obj[p], '
');
}

document. writeln('

');
}

A fact that is often overlooked by developers is that JavaScript itself does not have an event system. Usually
the onclick and other events we usually use in JavaScript are actually provided by IE's DOM model. From a more core
perspective: IE publishes a set of event interfaces to the DOM through the interface attributes of COM.

There are two reasons why "whether an attribute is an event" cannot be well identified in JS:
- The COM interface itself only has methods, properties and events, which are all passed through a set of get/ set method to publish.
- In JavaScript, there is no independent "event" mechanism.

So we see that the identification method of event is to detect whether the attribute name starts with the string 'on' (it is Qomo's convention to start with 'On'
). Next, since events in the DOM object do not need to specify a handler function, in this case the event handle is null (Qomo adopts the same convention); in other cases, the user can Like obj2, define an event with a value of undefined. Therefore, the judgment condition of "event" is processed
into a complex expression:
("The attribute starts with on/On" && ("The value is null/undefined" || "The type is function"))

In addition, judging from the running results of the above code. Using for..in on DOM objects cannot enumerate
object methods.

One final point. In fact, in many language implementations, "events" are not "object-oriented" language features, but are provided by specific programming models. For example, the event-driven mechanism in Delphi is provided by the window message mechanism in the Win32
operating system, or is implemented by user code actively calling the
event processing function in Component/Class.

"Events" are a mechanism/problem of "how to drive the programming model", not a problem of the language itself. However, the OOP concept based on PME (property/method/event) has been deeply rooted in the hearts of the people, so when the programming language or system shows these characteristics, no one cares about "event". Who achieved it?”

3). Use of this and with keywords
------
In the JavaScript object system, the this keyword is used in two places:
- in construction In the converter function, refers to the newly created object instance
- When the object's method is called, refers to the object instance that called the method

If a function is used as a normal function (rather than an object method) Called, then the this keyword
in the function will point to the window object. Similarly, if the this keyword is not in any function, then it also points to the
window object.

Because there is no clear distinction between functions and methods in JavaScript. So some of the code looks weird:
//------------------------------------------ --------------------
// Several possible calling forms of the function
//------------- -----------------------------------------------
function foo( ) {
// This below refers to the object instance that calls this method
if (this===window) {
document.write('call a function.', '
') ;
}
else {
document.write('call a method, by object: ', this.name, '
');
}
}

function MyObject(name) {
// This below refers to the newly created instance of the new keyword
this.name = name;
this.foo = foo;
}

var obj1 = new MyObject('obj1');
var obj2 = new MyObject('obj2');

// Test 1: Calling
foo() as a function;

// Test 2: Call as object method
obj1.foo();
obj2.foo();

// Test 3: Call function as "specified object" "Method call
foo.call(obj1);
foo.apply(obj2);

In the above code, obj1/obj2's call to foo() is a very common calling method . ——That is,
is a method to specify a function as an object on the constructor.

The call() and apply() in test 3 are quite special.

In this test, foo() is still called as an ordinary function, but the JavaScript language feature
allows an object instance to be passed in to specify foo() when calling()/apply() A reference to the this keyword that appears in the context of
. ——It should be noted that foo() at this time is still a normal
function call, not an object method call.

is somewhat similar to this "indicates the object instance that calls this method", and the with() syntax is also used to qualify
"use the object instance by default in a piece of code".——If the with() syntax is not used, then
then this code will be affected by the outer with() statement; if there is no outer with(), then
then the " The default object instance used will be window.

However, it should be noted that this and with keywords do not affect each other. Such as the following code:
//---------------------------------------- ------------------
// Test: this and with keywords do not affect each other
//---------- -----------------------------------------------
function test() {
with (obj2) {
this.value = 8;
}
}
var obj2 = new Object();
obj2.value = 10;

test();
document.writeln('obj2.value: ', obj2.value, '
');
document.writeln('window.value: ', window. value, '
');

You cannot expect such code to set the obj2.value attribute to 8 after the call is completed. The result of these lines of
code is: the window object has an additional value attribute, and the value is 8. The syntax

with(obj){...} can only limit the reading of the existing attributes of obj, but cannot actively
declare it. Once the object in with() does not have specified attributes, or with() qualifies a data that is not an object, the result will be an exception.

4). Operations using the in keyword
------
In addition to using for..in to reflect the member information of the object, JavaScript also allows direct use of in
Keyword to detect whether the object has an attribute with the specified name. The reason why the

in keyword is often mentioned is not its ability to detect whether the attribute exists, so in the early code of
, many people like to use "if (!obj.propName) {}" This way to detect whether propName
is a valid property. ——In many cases, checking validity is more
practical than checking “whether the attribute exists”. Therefore, in this case, in is only an optional and official solution. An important application of the

in keyword is high-speed string retrieval. Especially when you only need to determine "whether the string
exists". For example, if 100,000 strings are stored in an array, the retrieval efficiency will be
extremely poor.
//--------------------------------------------- ------------
// Use objects to retrieve
//--------------------- ----------------------------------
function arrayToObject(arr) {
for (var obj= new Object(), i=0, imax=arr.length; iobj[arr[i]]=null; }
return obj;
}

var
arr = ['abc', 'def', 'ghi']; // more and more...
obj = arrayToObject(arr);

function valueInArray(v) {
for (var i=0, imax=arr.length; iif (arr[i]==v) return true; }

return false;
}

function valueInObject(v) {
return v in obj;
}

This method of using the keyword in, There are also some limitations. For example, only strings can be found, while array elements can be any value. In addition, arrayToObject() also has some overhead, which makes it
unsuitable for frequently changing lookup sets. Finally, (I think you may have noticed) using the object
to search does not accurately locate the search data, while the array can point to the subscript of the result.

8. JavaScript object-oriented support
~~~~~~~~~~~~~~~~~~~
(continued)

2. JavaScript object-oriented Object support
--------
(continued)

5). Operation using instanceof keyword
------
in JavaScript The instanceof keyword is provided to detect the type of instance. This has already been discussed
before when discussing its "five-fold identity". But the problem with instanceof is that it always enumerates the entire
prototype chain to detect types (the principles of prototypal inheritance are described in the "Construction and Destruction" section), such as:
//------- --------------------------------------------------
//Problems in using instanceof
//---------------------------------- -----------------------
function MyObject() {
// ...
}

function MyObject2 () {
// ...
}
MyObject2.prototype = new MyObject();

obj1 = new MyObject();
obj2 = new MyObject2();

document.writeln(obj1 instanceof MyObject, '
');
document.writeln(obj2 instanceof MyObject, '
');

We see that obj1 and obj2 are both instances of MyObject, but they are generated by different constructors
. ——Note that this is correct in object-oriented theory: because obj2 is a subclass instance of MyObject, it has the same characteristics as obj1. In applications, this is one of the manifestations of obj2's polymorphism.

However, even so, we must face this problem: How to know whether obj2 and obj1 are
instances of the same type? ——In other words, even the constructors are the same?

The instanceof keyword does not provide such a mechanism. One that provides the ability to implement this detection is the
Object.constructor property. --But first remember, it's harder to use than you think.

Okay, let’s end the question first. The constructor attribute has already involved the issue of "construction and destruction".
We will talk about this later. "Prototypal inheritance" and "construction and destruction" are the main issues, core issues, and "fatal issues" in JavaScript's OOP
.

6). null and undefined
------
In JavaScript, null and undefined once confused me. The following text will help
you understand it more clearly (or make you more confused):
- null is the keyword; undefined is a property of the Global object.
- null is an object (empty object, without any properties and methods); undefined is a value of undefined class
type. Try the following code:
document.writeln(typeof null);
document.writeln(typeof undefined);
- In the object model, all objects are instances of Object or its subclasses, but Exception for null objects:
document.writeln(null instanceof Object);
- null is "equal (==)" to undefined, but not "congruent (===)" to undefined:
document.writeln(null == undefined);
document.writeln(null == undefined);
- Both null and undefined can be type converted to false during operation, but are not equal to false:
document.writeln(!null, !undefined);
document.writeln(null==false);
document.writeln(undefined==false);

8. JavaScript object-oriented support
~~~~~~~~~~~~~~~~~~
(continued)

3. Construction, destruction and prototype issues
----- ---
We already know that an object needs to be generated through a constructor function. Let’s remember a few points first:
- The constructor is an ordinary function
- The prototype is an object instance
- The constructor has prototype properties, but the object instance does not
- (If inheritance is implemented normally model, ) the constructor attribute of the object instance points to the constructor
- derived from the third and fourth items: obj.constructor.prototype points to the prototype of the object

OK, let’s analyze an example to illustrate JavaScript "Inherited prototype" declaration, with
and the construction process.
//--------------------------------------------- ------------
//Examples of understanding prototypes, construction, and inheritance
//-------------------- -------------------------------------
function MyObject() {
this. v1 = 'abc';
}

function MyObject2() {
this.v2 = 'def';
}
MyObject2.prototype = new MyObject();

var obj1 = new MyObject();
var obj2 = new MyObject2();

1). Formal code of new() keyword
------
Let’s first look at the new keyword in the line of code “obj1 = new MyObject()”. The

new keyword is used to generate a new instance (I would like to add here that I am used to calling reserved words key words
. In addition, the new keyword in JavaScript is also an operator) , the default attribute
of this instance will (at least) hold a reference to the prototype attribute (prototype) of the constructor function (in the ECMA Javascript
specification, this attribute name of the object is defined as __proto__) .

Every function, whether it is used as a constructor or not, will have a unique prototype object.
For JavaScript "built-in object constructor", it points to an internal prototype. By default, JavaScript
constructs an "empty initial object instance (not null)" and points the prototype reference to it. However, if you assign a new object to this prototype of the function, then the new object instance will hold a reference to it.

Next, the construction process will call MyObject() to complete the initialization. ——Note, this is just “initialization”.

In order to explain this process clearly, I use code to formally describe this process:
//--------------------- ------------------------------------
//Formal code of new() keyword
//--------------------------------------------- ------------
function new(aFunction) {
// Basic object instance
var _this = {};

// Prototype reference
var _proto= aFunction.prototype;

/* if compat ECMA Script
_this.__proto__ = _proto;
*/

// Add for accessing attributes in the prototype (internal) getter
_this._js_GetAttributes= function(name) {
if (_existAttribute.call(this, name))
return this[name]
else if (_js_LookupProperty.call(_proto , name))
retrun OBJ_GET_ATTRIBUTES.call(_proto, name)
else
return undefined;
}

// Add (internal) for accessing attributes in the prototype setter
_this._js_GetAttributes = function(name, value) {
if (_existAttribute.call(this, name))
this[name] = value
else if (OBJ_GET_ATTRIBUTES.call(_proto, name) !== value) {
this[name] = value // Create a new member of the current instance
}
}

// Call the constructor to complete initialization, (if any ,) Pass in args
aFunction.call(_this);

// Return object
return _this;
}

So we see the following two points:
- The constructor (aFunction) itself only "initializes" the passed this instance, and
does not construct an object instance.
- The construction process actually occurs inside the new() keyword/operator.

Furthermore, the constructor (aFunction) itself does not need to operate the prototype, nor does it need to return this.

2). Prototype chain maintained by user code
------
Next we will discuss the prototype chain and construction process in more depth. This is:
- The prototype chain is created by user code, the new() keyword does not assist in maintaining the prototype chain

Taking Delphi code as an example, when we declare the inheritance relationship, we can use this Code:
//------------------------------------------------ ----------------
// "Class" type declaration used in delphi
//----------------- ----------------------------------------
type
TAnimal = class (TObject); // Animal
TMammal = class(TAnimal); // Mammal
TCanine = class(TMammal); // Canine mammal
TDog = class(TCanine); // Dog

At this time, Delphi's compiler will maintain an inheritance relationship list through compilation technology. We can query this linked list through
code similar to the following:
//-------------------------------- ----------------------------
//Key code for using inheritance relationship linked list in delphi
//--- -------------------------------------------------- ----
function isAnimal(obj: TObject): boolean;
begin
Result := obj is TAnimal;
end;

var
dog := TDog ;

// ...
dog := TDog.Create();
writeln(isAnimal(dog));

You can see that in the Delphi user code , there is no need to directly inherit the linked list of the inheritance relationship. This is because
Delphi is a strongly typed language. When processing types declared with the class() keyword, Delphi's compiler
has already constructed this inheritance chain for the user. ——Note that this process is a statement, not an execution of
code.

In JavaScript, if you need to know whether an object is a subclass object of a certain base class, then
you need to manually maintain a linked list (similar to the Delphi example). Of course, this linked list is not called a type inheritance tree, but a "prototype linked list (of objects)". ——In JS, there is no "class" type.

Refer to the previous JS and Delphi code, a similar example is as follows:
//----------------------- ----------------------------------
//The key code of "prototype linked list" in JS
//-------------------------------------------------- ----------
// 1. Constructor
function Animal() {};
function Mammal() {};
function Canine() {};
function Dog() {};

// 2. Prototype linked list
Mammal.prototype = new Animal();
Canine.prototype = new Mammal();
Dog. prototype = new Canine();

// 3. Example function
function isAnimal(obj) {
return obj instanceof Animal;
}

var
dog = new Dog();
document.writeln(isAnimal(dog));

As you can see, in the JS user code, the construction method of the "prototype linked list" is a line of code:
"Constructor function of the current class".prototype = "Instance of the direct parent class"

This is different from languages ​​like Delphi: the essence of maintaining the prototype chain is to execute the code, not the declaration.

So, what does “execution rather than declaration” mean?

JavaScript will have a compilation process. This process mainly deals with "grammar error detection", "grammar declaration" and "conditional compilation instructions".The "grammar declaration" here mainly deals with function declarations. ——This is also one of the reasons why I say "functions are of the first type, but objects are not."

Example below:
//--------------------------------------------- ---------------------
//The relationship between function declaration and execution statement (firefox compatible)
//-------- --------------------------------------------------
// 1. Output 1234
testFoo(1234);

// 2. Try to output obj1
// 3. Try to output obj2
testFoo(obj1);
try {
testFoo(obj2);
}
catch(e) {
document.writeln('Exception: ', e.description, '
');
}

// Declare testFoo()
function testFoo(v) {
document.writeln(v, '
');
}

// Declare object
var obj1 = {};
obj2 = {
toString: function() {return 'hi, object.'}
}

// 4. Output obj1
// 5. Output obj2
testFoo(obj1);
testFoo(obj2);

The result of executing this sample code in the JS environment is:
------ -------------------------------
1234
undefined
Exception: 'obj2' undefined
[object Object]
hi, obj
------------------------------------------------
The problem is that testFoo() is executed before it is declared; while the object variable defined in the
form of "direct declaration" cannot be referenced before it is declared. ——In the example, the second and third
inputs are incorrect.

Functions can be referenced before declaration, while other types of values ​​must be used after declaration.
This shows that "declaration" and "execution-time reference" are two processes in JavaScript.

In addition, we can also find that when using "var" to declare, the compiler will first confirm that the variable
exists, but the value of the variable will be "undefined". ——So "testFoo(obj1)" will not
throw an exception. However, normal output will not occur until the assignment statement about obj1 is executed.
Please compare the differences between the output of the second and third lines and the fourth and fifth lines.

Since JavaScript maintains the prototype chain through "execution" rather than "declaration", this means that "the prototype
chain is maintained by user code rather than by the compiler.

Based on this inference, let’s look at the following example:
//-------------------------------- --------------------------
// Example: Wrong prototype chain
//--------- ---------------------------------------------
// 1. Constructor
function Animal() {}; // Animal
function Mammal() {}; // Mammal
function Canine() {}; // Canine mammals Animal

// 2. Construct prototype chain
var instance = new Mammal();
Mammal.prototype = new Animal();
Canine.prototype = instance;

// 3. Test output
var obj = new Canine();
document.writeln(obj instanceof Animal);

This output allows us to see a wrong prototype chain The result is that "canine mammals are not an animal".

The root cause is that the following lines of code in "2. Construct the prototype chain" are interpreted and executed, rather than "declared" and understood at compile time like var and
function. The way to solve the problem is to modify those three
lines of code to make its "execution process" logical:
//--------------------- ------------------------------------
//Correction code for the above example (part)
//--------------------------------------------- -----------
// 2. Construct the prototype chain
Mammal.prototype = new Animal();
var instance = new Mammal();
Canine.prototype = instance;

3). How prototype instances are used in the construction process
------
Still taking Delphi as an example. During the construction process, Delphi will first create an
"empty object" with a specified instance size, then assign values ​​to the properties one by one, call methods in the construction process, trigger events, etc.

The construction process implicit in the new() keyword in JavaScript is not completely consistent with the construction process of Delphi. But
the behavior that happens in the constructor function is similar to the above:
//-------------------------- -----------------------------
//Construction process in JS (formal code)
//- -------------------------------------------------- ------
function MyObject2() {
this.prop = 3;
this.method = a_method_function;

if (you_want) {
this.method( );
this.fire_OnCreate();
}
}
MyObject2.prototype = new MyObject(); // The declaration of MyObject() is omitted

var obj = new MyObject2 ();

If a single class is used as the reference object, JavaScript can have the same rich behavior as Delphi
during this construction process. However, since the construction process in Delphi is "dynamic", in fact
Delphi will also call the construction process of the parent class (MyObject) and trigger the OnCreate() event of the parent class.

JavaScript has no such feature. The construction process of the parent class only occurs on the line of code that assigns a value to the prototype (prototype
attribute). Afterwards, no matter how many new MyObject2() occur, the
MyObject() constructor will not be used. ——This also means:
- During the construction process, the prototype object is generated once; the new object only holds a reference to this prototype instance
(and uses the "copy-on-write" mechanism to access its properties) , and no longer calls the prototype's constructor.

Because the constructor of the parent class is no longer called, some features in Delphi cannot be implemented in JavaScript.
This mainly affects some events and behaviors in the construction phase. ——Some "during object construction process"
code cannot be written into the constructor of the parent class. Because no matter how many times the subclass is constructed, the construction process of the object this time will not activate the code in the parent class constructor at all.

The access of attributes in JavaScript is dynamic, because the object's access to parent class attributes depends on the prototype linked list, but the construction process of
is static and does not access the constructor of the parent class; in Delphi In some compiled languages, access to attributes (those that do not use readers and writers) is static, while the object's construction process dynamically calls the constructor of the parent class.
So once again, please read clearly this line in the formal code of the new() keyword:
//--------------------- ----------------------------------
//Formal code of new() keyword
//--------------------------------------------- -----------
function new(aFunction) {
// Prototype reference
var _proto= aFunction.prototype;

// ...
}

In this process, what JavaScript does is "get a prototype_Ref", while what other languages ​​such as Delphi do
is "Inherited Create()".

8. JavaScript object-oriented support
~~~~~~~~~~~~~~~~~~~
(continued)

4). Required Another attribute maintained by the user: constructor
------
Recalling the previous content, we mentioned:
- (If the inheritance model is implemented normally,) the constructor attribute of the object instance points to the constructor Object
- obj.constructor.prototype points to the prototype of the object
- Through the Object.constructor property, you can detect whether obj2 and obj1 are instances of the same type

and the prototype chain must be determined through user code Just like maintaining the prototype attribute, the constructor attribute constructor
of the instance also needs to be maintained by user code.

For JavaScript’s built-in objects, the constructor attribute points to the built-in constructor function. Such as:
//------------------------------------------------ ----------------
// Constructor attribute of built-in object instance
//-------------------- -------------------------------------
var _object_types = {
'function' : Function,
'boolean' : Boolean,
'regexp' : RegExp,
// 'math' : Math,
// 'debug' : Debug,
// 'image ' : Image;
// 'undef' : undefined,
// 'dom' : undefined,
// 'activex' : undefined,
'vbarray' : VBArray,
' array' : Array,
'string' : String,
'date' : Date,
'error' : Error,
'enumerator' : Enumerator,
'number' : Number,
'object' : Object
}

function objectTypes(obj) {
if (typeof obj !== 'object') return typeof obj;
if (obj == = null) return 'null';

for (var i in _object_types) {
if (obj.constructor===_object_types[i]) return i;
}
return ' unknow';
}

// Test data and related code
function MyObject() {
}
function MyObject2() {
}
MyObject2.prototype = new MyObject();

window.execScript(''
'Function CreateVBArray()'
' Dim a(2, 2)'
' CreateVBArray = a'
'End Function', 'VBScript');

document.writeln('
Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template