Skip to content
This repository was archived by the owner on Jul 12, 2025. It is now read-only.

Commit 6795960

Browse files
authored
Merge pull request #7 from wizard04wsu/dev
v10.0.0
2 parents 2479a65 + c7e3ecd commit 6795960

11 files changed

Lines changed: 631 additions & 639 deletions

.eslintrc.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"env": "es6",
3+
"extends": "eslint:recommended",
4+
"ecmaFeatures": {
5+
"impliedStrict": true
6+
}
7+
"files": [
8+
{
9+
"patterns": [ "**/*.mjs", "**/*.mjs.js" ],
10+
"sourceType": "module"
11+
}
12+
],
13+
}

README.md

Lines changed: 123 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1,130 +1,162 @@
11
# JavaScript Class Implementation
22

3-
This implementation allows for classes to be given protected access to items in a super-class.
3+
This implementation adds the capability for class instances to have [**protected members**](#readme-protected) that can be accessed by derivative class constructors.
44

5-
This is a JavaScript module.
5+
This is a JavaScript module. It can be imported into your script like so: `import Class from "Class.mjs.js"`
66

7-
---
7+
# Class.extend()
88

9-
## Creating subclasses
9+
Creates a child class. This is a static method of `Class` and its derivative classes.
1010

11-
**<samp>*Class*.extend([*options*])</samp>**
11+
## Syntax
1212

13-
Creates a new class that inherits from the parent class.
13+
```javascript
14+
Class.extend(initializer)
15+
Class.extend(initializer, applier)
16+
```
1417

15-
Parameters:
16-
- **<code>*options*</code>** {object}
17-
This can include any of the following:
18-
19-
- **<code>className</code>** {string}
20-
Used for the `name` property of the class constructor, and in the `toString` method for instances of the class. If not specified, it will be the same as the parent class.
21-
22-
- **<code>constructorFn</code>** {function}
23-
Initializes new instances of the class.<br><br>
24-
**<samp>*options*.constructorFn(*Super*[, ...])</samp>**<br><br>
25-
**<code>*Super*</code>** {function} is to be called from inside `constructorFn` to initialize the class, using the class's parent's constructor. It should be called as soon as possible, before using the `this` keyword, to ensure that the instance is properly initialized.<br><br>
26-
Additionally, <code>*Super*</code> provides access to protected members (<a href="#protected-members">see below</a>).
27-
28-
- **<code>returnFn</code>** {function}
29-
Returns a value when the constructor is called without using the `new` keyword.
18+
### Parameters
3019

31-
#### Example
20+
[**<code>*initializer*</code>**](#readme-initializer)
21+
A function to be executed by the constructor during the process of constructing a new instance of the child class. The name of the *<code>initializer</code>* is used as the name of the class.
3222

33-
```
34-
let Rectangle = Class.extend({
35-
className:"Rectangle",
36-
constructorFn:function (Super, width, height){
37-
Super();
38-
this.width = width||0;
39-
this.height = height||0;
40-
this.area = function (){ return Math.abs(this.width * this.height); };
41-
this.whatAmI = function (){ return "I am a rectangle."; };
42-
},
43-
returnFn:function (width, height){
44-
return Math.abs((width||0) * (height||0));
45-
}
46-
});
23+
**<code>*applier*</code>** *optional*
24+
A handler function for when the class is called without using the `new` keyword. Default behavior is to throw a [TypeError](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypeError).
4725

48-
let Square = Rectangle.extend({
49-
className:"Square",
50-
constructorFn:function (Super, width){
51-
Super(width, width);
52-
Object.defineProperty(this, "height", { get:function (){ return this.width; }, set:function (val){ this.width = 1*val||0; }, enumerable:true, configurable:true });
53-
let iAm = [this.whatAmI(), "I am a square."].join(" ");
54-
this.whatAmI = function (){ return iAm; };
55-
},
56-
returnFn:function (width){
57-
return Math.pow(width||0, 2);
58-
}
59-
});
26+
### Return value
6027

61-
let s = new Square(3);
28+
The new class constructor. It has its own static copy of the `extend` method.
6229

63-
s.toString(); //[instance of Square]
64-
s.area(); //9
65-
s.height = 4;
66-
s.area(); //16
67-
s.whatAmI(); //I am a rectangle. I am a square.
30+
<a name="readme-initializer"></a>
31+
### Initializer
6832

33+
The signature of the *<code>initializer</code>* function is expected to be:
34+
```javascript
35+
function MyClassName($super, ...args){
36+
//code that does not include `this`
37+
const protectedMembers = $super(...args);
38+
//code that may include `this`
39+
}
6940
```
7041

71-
### Protected members
42+
**<code>*$super*</code>**
43+
A [Proxy](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy) to the parent class's constructor, bound as the first argument of the *<code>initializer</code>*. It is to be used like the [`super`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/super) keyword. It *must* be called exactly once during the execution of the constructor, *before* any reference to `this`.
7244

73-
A class can give its descendants protected access to its private variables. Once <code>*Super*</code> is called within the constructor, the protected properties of its parent class are made available via **<code>*Super*.protected</code>**. This object will be available to child classes as well; any additions/deletions/overloads of its members that are made here in the constructor will be reflected in the class' descendants.
45+
<a name="readme-protected"></a>
46+
**<code>*protectedMembers*</code>**
47+
An object whose members are shared among all the <i><code>initializer</code></i>s that are executed when a new instance of the class is created. This allows a protected value defined in the *<code>initializer</code>* of a class to be accessed and modified within the *<code>initializer</code>* of a derivative class directly, without needing static getters and setters.
7448

75-
#### Example
49+
## Examples
7650

77-
```
78-
let Alpha = Class.extend({
79-
className:"Alpha",
80-
constructorFn:function (Super){
81-
Super();
82-
let randomInstanceID = Math.random();
83-
Super.protected.rando = randomInstanceID;
84-
}
85-
});
51+
### Create a new class
8652

87-
let Bravo = Alpha.extend({
88-
className:"Bravo",
89-
constructorFn:function (Super){
90-
Super();
91-
this.foo = "My ID is "+Super.protected.rando;
92-
}
53+
```javascript
54+
const MyClass = Class.extend(function Rectangle($super, width, height){
55+
$super();
56+
this.dimensions = ()=>width+" x "+height;
9357
});
9458

95-
let b = new Bravo();
59+
let r = new MyClass(2, 3);
60+
61+
console.log(MyClass.name); // Rectangle
62+
console.log(r.toString()); // [object Rectangle]
63+
console.log(r.dimensions()); // 2 x 3
64+
```
65+
66+
### Use an applier function
9667

97-
b.foo; //My ID is ...
68+
```javascript
69+
const Rectangle = Class.extend(function Rectangle($super, width, height){
70+
$super();
71+
this.dimensions = ()=>width+" x "+height;
72+
},
73+
(width, height)=>"area = "+(width*height) //applier function for when Rectangle() is called without using `new`
74+
);
9875

76+
console.log((new Rectangle(2, 3)).toString()); // [object Rectangle]
77+
console.log(Rectangle(2, 3)); // area = 6
9978
```
10079

80+
### Inherit from a superclass
10181

102-
---
82+
```javascript
83+
const Rectangle = Class.extend(function Rectangle($super, width, height){
84+
$super();
85+
this.dimensions = ()=>width+" x "+height;
86+
});
10387

104-
### Private members
88+
const Square = Rectangle.extend(function Square($super, width){
89+
$super(width, width);
90+
//this.dimensions() is inherited from Rectangle
91+
});
10592

106-
A WeakMap or a symbol can be used to implement private members for class instances, allowing functions defined both inside and outside of the constructor to share data.
93+
let s = new Square(2);
10794

108-
#### Example using a WeakMap
95+
console.log(s.dimensions()); // 2 x 2
96+
```
97+
98+
### Use static methods of the parent class
99+
100+
```javascript
101+
const Rectangle = Class.extend(function Rectangle($super, width, height){
102+
$super();
103+
this.dimensions = ()=>width+" x "+height;
104+
});
105+
Rectangle.area = function (width, height){ return width * height; };
109106

107+
const Square = Rectangle.extend(function Square($super, width){
108+
$super(width, width);
109+
this.area = function (){
110+
return $super.area(width, width); //here, using `$super` as an object is equivalent to using `Rectangle`
111+
};
112+
});
113+
114+
let s = new Square(2);
115+
116+
console.log(Rectangle.area(2, 2)); // 4
117+
console.log(s.area()); // 4
110118
```
111-
let Cuber = (function (){
112-
113-
const private = new WeakMap();
119+
120+
### Use protected members
121+
122+
```javascript
123+
const Rectangle = Class.extend(function Rectangle($super, width, height){
124+
const prot = $super();
114125

115-
function cube(){ return Math.pow(private.get(this).val, 3); }
126+
prot.width = width;
127+
prot.height = height;
116128

117-
return Class.extend({
118-
constructorFn: function (Super, myVal){
119-
Super();
120-
private.set(this, { val: myVal });
121-
this.cube = cube;
122-
}
129+
Object.defineProperty(this, "width", {
130+
enumerable: true, configurable: true,
131+
get(){ return prot.width; },
132+
set(width){ return prot.width = width; }
133+
});
134+
Object.defineProperty(this, "height", {
135+
enumerable: true, configurable: true,
136+
get(){ return prot.height; },
137+
set(height){ return prot.height = height; }
123138
});
124139

125-
})();
140+
this.dimensions = ()=>prot.width+" x "+prot.height;
141+
});
126142

127-
let c = new Cuber(5);
143+
const Square = Rectangle.extend(function Square($super, width){
144+
const prot = $super(width, width);
145+
146+
Object.defineProperty(this, "width", {
147+
enumerable: true, configurable: true,
148+
get(){ return prot.width; },
149+
set(width){ return prot.width = prot.height = width; }
150+
});
151+
Object.defineProperty(this, "height", {
152+
enumerable: true, configurable: true,
153+
get(){ return prot.height; },
154+
set(height){ return prot.height = prot.width = height; }
155+
});
156+
});
128157

129-
c.cube(); //125
158+
let s = new Square(2);
159+
console.log(s.dimensions()); // 2 x 2
160+
s.height = 3;
161+
console.log(s.dimensions()); // 3 x 3
130162
```

dist/Class_8_0_0.min.js

Lines changed: 0 additions & 1 deletion
This file was deleted.

0 commit comments

Comments
 (0)