Home Web Front-end JS Tutorial Introducing a simple JavaScript class framework_Basic knowledge

Introducing a simple JavaScript class framework_Basic knowledge

May 16, 2016 pm 03:52 PM
javascript frame

When writing the work-in-progress JavaScript book, I spent a considerable amount of time on the JavaScript inheritance system, and in the process studied various different solutions for simulating classic class inheritance. Among these technical solutions, the implementation of base2 and Prototype is the one I admire most.

From these solutions, a framework with its ideological connotation should be extracted. The framework must be simple, reusable, easy to understand, and independent of dependencies. Simplicity and usability are the key points. Here are usage examples:

var Person = Class. extend ( {
 init: function (isDancing ) {
  this. dancing = isDancing;
 },
 dance: function ( ) {
  return this. dancing;
 }
} );
var Ninja = Person.extend({
 init: function(){
  this._super( false );
 },
 dance: function(){
  // Call the inherited version of dance()
  return this._super();
 },
 swingSword: function(){
  return true;
 }
});
var p = new Person(true);
p.dance(); // => true
var n = new Ninja();
n.dance(); // => false
n.swingSword(); // => true
// Should all be true
p instanceof Person && p instanceof Class &&
n instanceof Ninja && n instanceof Person && n instanceof Class
Copy after login

There are a few things to note:

  • The constructor must be simple (implemented through the init function),
  • The newly defined analogy must inherit from the existing class,
  • All ‘classes’ inherit from the ancestor class: Class, so if you want to create a brand new class, the class must be a subclass of Class,
  • The most challenging point: the overridden method of the parent class must be accessible (through the configuration context).
  • In the above example, you can find that the init() and dance() methods of the Person parent class are called through this._super().

Quite happy with the results: made the class definition structured, kept single inheritance, and was able to call superclass methods.

Simple class creation and inheritance

The following is its implementation (easy to read and has comments), about 25 lines. Suggestions are welcome and appreciated.

/* Simple JavaScript Inheritance
 * By John Resig http://ejohn.org/
 * MIT Licensed.
 */
// Inspired by base2 and Prototype
( function ( ) {
 var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;
 // The base Class implementation (does nothing)
 this.Class = function(){};
  
 // Create a new Class that inherits from this class
 Class.extend = function(prop) {
  var _super = this.prototype;
   
  // Instantiate a base class (but only create the instance,
  // don't run the init constructor)
  initializing = true;
  var prototype = new this();
  initializing = false;
   
  // Copy the properties over onto the new prototype
  for (var name in prop) {
   // Check if we're overwriting an existing function
   prototype[name] = typeof prop[name] == "function" &&
    typeof _super[name] == "function" && fnTest.test(prop[name]) ?
    (function(name, fn){
     return function() {
      var tmp = this._super;
       
      // Add a new ._super() method that is the same method
      // but on the super-class
      this._super = _super[name];
       
      // The method only need to be bound temporarily, so we
      // remove it when we're done executing
      var ret = fn.apply(this, arguments);    
      this._super = tmp;
       
      return ret;
     };
    })(name, prop[name]) :
    prop[name];
  }
   
  // The dummy class constructor
  function Class() {
   // All construction is actually done in the init method
   if ( !initializing && this.init )
    this.init.apply(this, arguments);
  }
   
  // Populate our constructed prototype object
  Class.prototype = prototype;
   
  // Enforce the constructor to be what we expect
  Class.prototype.constructor = Class;
  // And make this class extendable
  Class.extend = arguments.callee;
   
  return Class;
 };
})();
Copy after login

Among them, "initializing/don't call init" and "creating _super method" are the most difficult. Next, I will give a brief introduction to this so that everyone can better understand its implementation mechanism.

Initialization

In order to illustrate the function prototype inheritance method, let’s first look at the traditional implementation process, which is to point the prototype attribute of the subclass to an instance of the parent class. As shown below:


function Person ( ) { }
function Ninja ( ) { }
Ninja. prototype = new Person ( );
// Allows for instanceof to work:
(new Ninja()) instanceof Person
Copy after login

However, the challenging point here is that we only want to get the effect of ‘instatnceOf’, without the consequences of instantiating a Person and calling its constructor. To prevent this, set a bool parameter initializing in the code, whose value will be true only when the parent class is instantiated and configured to the prototype property of the child class. The purpose of this processing is to distinguish the difference between calling the constructor during real instantiation and design inheritance, and then call the init method during real instantiation:

if ( !initializing )
 this.init.apply(this, arguments);
Copy after login

It is worth paying special attention to because in the init function, quite resource-intensive code may be run (such as connecting to the server, creating DOM elements, etc., no one can predict), so it is completely necessary to make a distinction.

Super Method

When using inheritance, the most common requirement is that the subclass can access the overridden methods of the superclass. In this implementation, the final solution is to provide a temporary method (._super) that points to the superclass method and can only be accessed in the subclass method.

var Person = Class. extend ( {
 init: function (isDancing ) {
  this. dancing = isDancing;
 }
} );
var Ninja = Person.extend({
 init: function(){
  this._super( false );
 }
});
var p = new Person(true);
p.dancing; // => true
var n = new Ninja();
n.dancing; // => false
Copy after login


Implementing this functionality requires several steps. First, we use extend to merge the basic Person instance (class instance, whose construction process we mentioned above) with the literal object (function parameter of Person.extend()). During the merging process, a simple check was made: first check whether the attribute to be merged is a function, if so, then check whether the superclass attribute to be overwritten is also a function? If both checks are true, you need to prepare a _super method for this property.

Note that an anonymous closure (returning a function object) is created here to encapsulate the added super method. Based on the need to maintain the running environment, we should save the old this._super (whether it exists or not) to be reset after the function is run. This helps in cases where there is the same name (don't want to accidentally lose the object pointer) Unpredictable problems.

Then, create a new _super method that points only to the overridden method in the super class. Thank God, there is no need to make any changes to _super or change the scope, because the execution environment of the function will automatically change with the function calling object (the pointer this will point to the super class).

Finally, call the method of the literal object. This._super() may be used during method execution. After the method is executed, the attribute _super is reset to its original state, and then return exits the function.


There are many ways to achieve the same effect (I have seen binding super to itself before and then accessing it with arguments.callee), but I feel that this method best reflects the characteristics of usability and simplicity.

Among the many works based on JavaScript prototypes that I have completed, this is the only class inheritance implementation plan that I have published to share with you. I think that concise code (easy to learn, easy to inherit, less downloading) needs to be put forward for everyone to discuss. Therefore, for people who learn JavaScript class construction and inheritance, this implementation plan is a good start.

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

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

How to evaluate the cost-effectiveness of commercial support for Java frameworks How to evaluate the cost-effectiveness of commercial support for Java frameworks Jun 05, 2024 pm 05:25 PM

Evaluating the cost/performance of commercial support for a Java framework involves the following steps: Determine the required level of assurance and service level agreement (SLA) guarantees. The experience and expertise of the research support team. Consider additional services such as upgrades, troubleshooting, and performance optimization. Weigh business support costs against risk mitigation and increased efficiency.

How do the lightweight options of PHP frameworks affect application performance? How do the lightweight options of PHP frameworks affect application performance? Jun 06, 2024 am 10:53 AM

The lightweight PHP framework improves application performance through small size and low resource consumption. Its features include: small size, fast startup, low memory usage, improved response speed and throughput, and reduced resource consumption. Practical case: SlimFramework creates REST API, only 500KB, high responsiveness and high throughput

How does the learning curve of PHP frameworks compare to other language frameworks? How does the learning curve of PHP frameworks compare to other language frameworks? Jun 06, 2024 pm 12:41 PM

The learning curve of a PHP framework depends on language proficiency, framework complexity, documentation quality, and community support. The learning curve of PHP frameworks is higher when compared to Python frameworks and lower when compared to Ruby frameworks. Compared to Java frameworks, PHP frameworks have a moderate learning curve but a shorter time to get started.

Performance comparison of Java frameworks Performance comparison of Java frameworks Jun 04, 2024 pm 03:56 PM

According to benchmarks, for small, high-performance applications, Quarkus (fast startup, low memory) or Micronaut (TechEmpower excellent) are ideal choices. SpringBoot is suitable for large, full-stack applications, but has slightly slower startup times and memory usage.

Golang framework documentation best practices Golang framework documentation best practices Jun 04, 2024 pm 05:00 PM

Writing clear and comprehensive documentation is crucial for the Golang framework. Best practices include following an established documentation style, such as Google's Go Coding Style Guide. Use a clear organizational structure, including headings, subheadings, and lists, and provide navigation. Provides comprehensive and accurate information, including getting started guides, API references, and concepts. Use code examples to illustrate concepts and usage. Keep documentation updated, track changes and document new features. Provide support and community resources such as GitHub issues and forums. Create practical examples, such as API documentation.

How to choose the best golang framework for different application scenarios How to choose the best golang framework for different application scenarios Jun 05, 2024 pm 04:05 PM

Choose the best Go framework based on application scenarios: consider application type, language features, performance requirements, and ecosystem. Common Go frameworks: Gin (Web application), Echo (Web service), Fiber (high throughput), gorm (ORM), fasthttp (speed). Practical case: building REST API (Fiber) and interacting with the database (gorm). Choose a framework: choose fasthttp for key performance, Gin/Echo for flexible web applications, and gorm for database interaction.

What are the common misunderstandings in the learning process of Golang framework? What are the common misunderstandings in the learning process of Golang framework? Jun 05, 2024 pm 09:59 PM

There are five misunderstandings in Go framework learning: over-reliance on the framework and limited flexibility. If you don’t follow the framework conventions, the code will be difficult to maintain. Using outdated libraries can cause security and compatibility issues. Excessive use of packages obfuscates code structure. Ignoring error handling leads to unexpected behavior and crashes.

Detailed practical explanation of golang framework development: Questions and Answers Detailed practical explanation of golang framework development: Questions and Answers Jun 06, 2024 am 10:57 AM

In Go framework development, common challenges and their solutions are: Error handling: Use the errors package for management, and use middleware to centrally handle errors. Authentication and authorization: Integrate third-party libraries and create custom middleware to check credentials. Concurrency processing: Use goroutines, mutexes, and channels to control resource access. Unit testing: Use gotest packages, mocks, and stubs for isolation, and code coverage tools to ensure sufficiency. Deployment and monitoring: Use Docker containers to package deployments, set up data backups, and track performance and errors with logging and monitoring tools.

See all articles