"Introduction" in business modeling, we often encounter a situation where the "prototype" object is responsible for the basic requirements of the business (including: what attributes, what functions, and the relationships between them), and the "sub-objects" that are created on the basis of the "prototype" object implement some personalized business features to facilitate business expansion. The most common pointers are:
1. Define a ' constructor ' where the initialization of the property is implemented, for example: var person = function () {}; Some variables can be initialized in the body of the function.
2. Set the prototype member of the function again, for example: Person.prototype = {gotoschool:function () {Console.log (' onfoot');}}; Some methods are defined in the object literal
3. Use new to create a new object, for example: var student = new Person ();
4. Partial behavior of the personalization new object: Student.gotoschool = function () {Console.log (' by Bus ');};
>> invoke Student.gotoschool () according to the characteristics of new and prototype chains; The by bus will be output instead of on foot.
5. Similarly, use new to create a teacher object, and then set its gotoschool members.
var New Person (); = function() {Console.log (' by car ' );}; Teacher.gotoschool (); //
Description: The code in this article can perform validation in the Chrome browser's console. Here's how: Click the Console tab after pressing F12 and open Chrome's console to see the results of the console.log output.
The above approach satisfies our basic requirements, and we do so in our previous Web control custom development. However, if the business model is more complex, then the drawbacks of this approach are obvious:
Without a private environment, all properties are public.
Today, let's start with business modeling and see if there's a better way to gracefully implement business modeling with JavaScript's closure features.
Let's look at an example of a prototype inheritance:
1 varBaseobject = (function(){2 varthat = {};3 4That.name = ' Lily ' ;5That.sayhello =function(){6Console.log (' Hello ' + This. GetName ());7 };8That.getname =function(){9 return This. Name;Ten }; One A returnthat ; - })(); - the //to create an inherited object - varTomobject =object.create (baseobject); -Tomobject.name = ' Tom ' ; - + //calling a public method -Tomobject.sayhello ();//output: Hello Tom
Analysis
The current way, in the case of coding norms, is able to work normally, but from the point of view of the package of the program, there are obvious deficiencies.
Because, Tomobject can also set its getname function,
For example: in Tomobject.sayhello (), before adding the following code:
//....
Tomobject.getname = function () {return ' Jack '};
Calling a public method
Tomobject.sayhello (); Output: Hello Jack
In fact, as a convention, we want GetName to call the property value of the name of the current object and not allow any child objects that inherit it to overwrite it arbitrarily! In other words, getname should be a private function!
Now, let's look at how to solve this problem with "closures":
1 varCREATEPERSONOBJFN =function(){2 varthat = {};3 4 varname = ' Lily ' ;5 6 varGetName =function(){7 returnname;8 };9 TenThat.setname =function(new_name) { OneName =new_name; A }; -That.sayhello =function(){ -Console.log (' Hello ' +getName ()); the }; - - returnthat ; - }; + - //Create an Object + varTomobject =Createpersonobjfn (); ATomobject.setname (' Tom ') ); at - //calling a public method -Tomobject.sayhello ();//output: Hello Tom
Analysis
Now, although you can still add a new getname () function to Tomobject, it does not affect SayHello's business logic. Similarly
//...
Tomobject.setname (' Tom ');
Tomobject.getname = function () {return ' Jack ';}; function to set the getname of an object
Calling a public method
Tomobject.sayhello (); Still output: Hello Tom
Closures are characterized by:
1. Save the properties of the ' business object ' in the ' Runtime environment '.
2. Natural ' Factory mode ', to be reborn as an object, execute the function.
From this, it can be seen that the ' closure ' of this model to build a business, the ' prototype chain ' understanding of the requirements are not high, this may be why the "prototype chain" in its book is very little of the reason for it.
Optimization
However, we know that in the business model, we still want to be able to achieve the "inheritance" effect, that is, "principal object" to implement the basic framework and logic, "sub-object" according to its own characteristics to customize some specific behavior. When creating an object from Object.create (), based on the "prototype chain" feature, we understand that it is OK to redefine the custom function in the newly created object. But what about the same business demands that are implemented in the ' closures ' approach?
Method
In a function that is exposed by a closure, a function called through this is called, and the function's behavior can be customized outside of the closure.
The test code is as follows:
1That.sayhello =function(){2 //the SayHello here invokes the Getnewname () of the current object .3Console.log (' Hello ' + This. Getnewname ()); 4 };5 6 //... The other code in front of you is not changed7 varTomobject =Createpersonobjfn ();8Tomobject.getnewname =function(){//defines the getnewname of the current object,9 return' Jack ' ;Ten } One A //calling a public method -Tomobject.sayhello ();//output: Hello Jack
Analysis
Although we seem able to customize some of the behavior of an object by modifying the definition in SayHello (by invoking a method function), however, the newly defined behavior does not have access to the private properties of Tomobject name! It has absolutely nothing to do with what the object originally wanted to say. Perhaps this is true of our business aspirations, and after customizing the behavior, SayHello is able to print the contents of "Hello Dear tom!" or "Hello my tom!".
[Review] We know that in closures, if you want to access a private property, you must define the associated public method. So, we optimize as follows:
1 //... In closures, a function such as GetName is converted from a private function to a public function2That.getname =function( ){3 returnname;4 }5 6 //... Define the Tomobject custom function Getnewname, calling the GetName method in the function. 7Tomobject.getnewname =function(){8 return' Dear ' + tomobject.getname () + '! ' ;9 }TenTomobject.setname (' Tom ') ); One A //calling a public method -Tomobject.sayhello ();//output: Hello Dear tom! - the - //to reflect the characteristics of custom behavior, we create another Jack object . - varJackobject =Createpersonobjfn (); -Jackobject.getnewname =function(){//defines the getnewname of the current object, + return' My ' + jackobject.getname () + '! ' ; - } +Jackobject.setname (' Jack ' ); A at //calling a public method -Jackobject.sayhello ();//output: Hello my jack!
Analysis
There seems to be no problem, but there is a small detail that needs to be optimized. We call This.getnewname () in SayHello, but if the newly created object does not redefine the Getnewname function,
Wouldn't that be an unusual report? Therefore, the rigorous practice should be, in the closure also set a That.getnewname function, the default behavior is to return the current name value,
If custom behavior is to be performed, the object will reflect the custom behavior, overriding (overloading) the default behavior.
"A complete example"
1. In closures, you can define private attributes (that is, objects, strings, numbers, Boolean types, and so on), which can only be accessed and modified by a function that is open by a closure.
2. Some functions, you do not want the external object to call it, just for the function within the closure (including: public functions and private functions) call, you can define it as a private function.
3. If you want a part of a closure object to be customizable (to achieve an inherited effect), you need to do the following steps.
A. Add public functions that can access private properties, such as the GetName function in the example.
Because, according to the scope, the outside of the closure is inaccessible to private properties, and the custom function is outside the closure.
B. Inside the closure, set the default behavior of the custom function, such as the definition of the Getnewname function in the closure, in the form of a public function.
C. In a public function that allows custom behavior (for example, the SayHello function in the example), a function that can customize the behavior is called through this.
For example, This.getnewname ().
The complete code is as follows:
1 varCREATEPERSONOBJFN =function(){2 varthat = {};3 4 varname = ' Lily ' ;5 6That.getname =function(){7 returnname;8 };9That.setname =function(new_name) {TenName =new_name; One }; AThat.getnewname =function( ){//the default behavior - returnname; - }; theThat.sayhello =function(){ -Console.log (' Hello ' + This. Getnewname ()); - }; - + returnthat ; - }; + A //1. Create an Object at varTomobject =Createpersonobjfn (); -Tomobject.getnewname =function(){ - return' Dear ' + tomobject.getname () + '! ' ; - } -Tomobject.setname (' Tom ') ); - in //calling a public method -Tomobject.sayhello ();//output: Hello Dear tom! to + //2. Create an object for another Jack - varJackobject =Createpersonobjfn (); theJackobject.getnewname =function(){//defines the getnewname of the current object, * return' My ' + jackobject.getname () + '! ' ; $ }Panax NotoginsengJackobject.setname (' Jack ' ); - the //calling a public method +Jackobject.sayhello ();//output: Hello my jack! A the + //3 Create another Bill object, do not redefine the Getnewname function, take the default behavior - varBillobject =Createpersonobjfn (); $Billobject.setname (' Bill ' ); $ - //calling a public method -Billobject.sayhello ();//output: Hello Bill
Summary
JavaScript is a highly expressive language, very flexible, and naturally more prone to error. In the example above, we only highlight the characteristics of closures, in fact, using the "prototype chain" characteristics, we can completely based on tomobject,jackobject these objects to create additional objects, or tomobject the creation of these objects, put in another closure, This may make it possible to combine a richer model. The characteristics of closures are here, and the characteristics of the prototype chain are here ... When is it going to work? How do you mix it up with? The key is to look at our business requirements, see the real use of the scene, see our performance, scalability, security and many other aspects of expectations.
In addition, this article involves some background knowledge, such as: What is the prototype chain of a graph relationship? What does the new operator do when the object is created? How can object.create be understood? As space is limited, it is not open to say that, if there are any questions or suggestions, please point out the discussion, thank you.
"Think again."
The attentive classmate may have found out that since the implementation of That.getnewname and that.getname in closures is exactly the same, why do you want to define these two functions repeatedly? Is it possible to remove the that.getname in the closure package?
The answer is, of course, negative. If you delete the That.getname in the closure and you redefine the That.getnewname method, the private property name in the closure cannot be accessed outside the closure.
This is like the paper in the same bag of tissues, it looks exactly the same, but the responsibilities are different, some are used beforehand, some are afterwards used.
For example, if you eat an apple in the park without a fruit knife, you will first pull out a piece of paper (a) wipe the Apple's appearance, finish the apple, wrap the Apple's core paper in the Trash, and pull out a piece of paper (B) to wipe your mouth and hands.
Because everyone is hygiene, understand the civilized "four new".
Today's share to this end, thank you for your welcome, I hope you are not hesitate to enlighten.
Business modeling gossip ' closures ' and ' prototype inheritance '