How to make a class in JavaScript?

匿名 (未验证) 提交于 2019-12-03 01:00:01

问题:

There are lots of ways of doing the same thing in JavaScript. I have however picked up some ways, and some ways I frankly don't understand. Could anyone please help me clarify some things? (I first learnt OOP in PHP.)

So a class can be made like this:

var object = new class(constructparams) {     var private_members; // Can be accessed from within the code inside this definition only.     this.public_members; // Can be accessed from everywhere.      var private_functions = function() {}     this.public_functions = function() {} }  object.prototype.semi_public_members = function() {     // Will be public, but can only access public members and methods.     // E. g. private_members; is not available here. } 

Is this all correct so far?

Then someone likes the self-executing anonymous function approach to create a namespace. What is the point of that, when you have this way above that does the same thing, provides a namespace?

And lastly you have the object literal notation that I don't understand.

var object = { // Something strange in here } 

What is going on in there? Is it JSON? How is it used, how can I use it. What are the benefits of using this way instead of using the method I described? Why would you prototype instead of making the class correctly the first time?

回答1:

Explaining the behaviour of different things in a constructed object by example:

// Defined as a variable from an anonymous function // so that there is scope closure over variables // shared across all instances and the prototype. // If this isn't important, you don't need to close // scope around it, so define directly var ConstructedObject = (function constructorCreator () {     // Define any variables/methods to be shared across     // all instances but not polluting the namespace     var sharedVariable = 'foo';      // Next the actual constructor     function ConstructedObject () {         // Variables here are normally used to help         // each instance and will be kept in memory as         // long as the instance exists         var instanceVariable = 'bar';         // instance-specific properties get defined         // using the "this" keyword, these are the         // properties expected to be changed across         // each different instance         this.instanceProperty = true;         this.instanceMethod = function () { return instanceVariable; };         this.changeInstanceVar = function () { instanceVariable = 'foo'; };             // you do have access to the shared             // variables here if you need them.     }     // After the constructor, you set up the     // prototype, if any. This is an object of shared     // properties and methods to be inherited by every     // instance made by the constructor, and it also     // inherits the prototype's prototype, too.     // Lets use a literal object for simplicity.     ConstructedObject.prototype = {         // Accessing the instance to which a method         // applies is done using the "this" keyword,         // similar to in the constructor         sharedMethod : function () { return [sharedVariable, this.instanceMethod(),this.instanceProperty]; },         changeSharedVar : function () { sharedVariable = 'bar'; }         // properties may also be defined     };     // Finally, the constructor is returned so it     // can be kept alive outside of the anonymous     // function used to create it     return ConstructedObject; // and the anonymous function is called to execute // what we've done so far })(); 

After executing the above code, you have a constructor that creates objects with both instance-specific and shared variables. Now let's look at how they behave by creating two of instances and comparing them before and after some changes.

// First create the two instances var myObjA = new ConstructedObject(),     myObjB = new ConstructedObject(); // Now compare them, the sharedMethod method we // used in the prototype offers an easy way to // do this console.log( myObjA.sharedMethod(), myObjB.sharedMethod() ); // ["foo", "bar", true] ["foo", "bar", true] // Next lets change the different variables in // myObjB so we can see what happens, again the // change* methods defined before let us do this // easily myObjB.changeInstanceVar(); myObjB.changeSharedVar(); // For completeness, lets also change the property // on myObjB. myObjB.instanceProperty = false; // Now when we compare them again, we see that our // changes to the myObjB instance have only changed // the shared variables of myObjA console.log( myObjA.sharedMethod(), myObjB.sharedMethod() ); // ["bar", "bar", true] ["bar", "foo", false] 

Here are the two logged statements together for easier viewing

//     myObjA               myObjB ["foo", "bar", true] ["foo", "bar", true] ["bar", "bar", true] ["bar", "foo", false] 


回答2:

I think there are some concepts that seem to be missing but I'll try answering as much as I can.

So a class can be made like this...Is this all correct so far?

It's close but is not entirely correct. You don't need new to create a constructor function, you only need it when creating a new instance of the "class".

function Klass() { ... } // capitalized name as convention for constructors var myKlass = new Klass(); //

Public methods can be attached to the instance or to the prototype. When you attach it to the prototype the method will be shared across all instances, saving some memory.

Klass.prototype = {   publicSharedMethod: function() {     var self = this;   } } 

Then someone likes the self-executing anonymous function... What is the point of that...

The module pattern (or self-execution function) approach is a bit different because you're typically not dealing with the prototype although you can. It's just a function that returns a literal object with properties and methods but I mainly use it for singletons when you don't need instances of that object:

var Singleton = (function() {   var private = 'foo';   var public = 'baz';   var publicMethod = function() { ... }   // Expose public methods and properties   return {     public: public     publicMethod: publicMethod   } }()); 

And lastly you have the object literal notation that I don't understand.

That's just a regular object in JavaScript, similar to what PHP calls "associative array". Literal objects syntax are the base for JSON, but JSON has more limitations in terms of formatting; JavaScript is more forgiving so you can have unquoted properties and methods for example.

Why would you prototype instead of making the class correctly the first time?

The point here is to understand that JavaScript is not a traditional object oriented language, so there are no classes, and you shouldn't be thinking about classes. But prototypes are very powerful, I'd say even more powerful than classes. There are many examples online on how to replicate classes with prototypes but not the other way around.



回答3:

var object = new function () {     // }  var myObject = new object(); 


回答4:

No, that is not correct. The constructor function should be separate from the creation of the object:

function myClass(constructparam1) {   this.public_member = constructparam1; // Can be accessed from everywhere. } 

The methods should be in the prototype for the constructor, not the instance:

myClass.prototype.semi_public_members = function() {   // Will be public } 

Call the constructor with the new keyword to create the instance:

var obj = new myClass(1337); 

Local variables inside the constructor function can only be accessed inside that function. If you wan't local variables in your class, you need a function around it to create a closure, so that the methods in the prototype can access the variables:

var myClass = (function(){    var local_variable;    function constructor(constructparam1) {     this.public_member = constructparam1; // Can be accessed from everywhere.   }    constructor.prototype.semi_public_members = function() {     // Will be public     alert(local_variable); // can access private variables   }    return constructor; })(); 

Object literals is just a simple but limited way to create objects in one go. They don't have a prototype, so if you want them to have methods, you have to assign them to properties:

var obj = {    public_member: 1337,    semi_public_members: function(){     alert(this.public_member);   }  }; 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!