-
-
Notifications
You must be signed in to change notification settings - Fork 286
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Consider factory functions #24
Comments
Yeah, that's true... would simplify a lot. I personally prefer ES6 classes 'cause I use babel anyway and it will be transpiled to ES5 constructor functions. And they are more legible IMO. But you're basically right, I will take this in consideration / try it out. |
I agree factories are not as clean looking as classes, that's fair 😐. |
Hahaha, thank's 😄, I will have! |
class vs factory function: general structure comparisonthis is just for interest's sake. classesclass X {
constructor (props) {
Object.assign(this, {...X.defaults}, props)
}
method () {
// do something
console.log(`state: a: ${this.a}, b: ${this.b}, c: ${this.c}`)
}
// ... more methods ...
}
// static defaults
X.defaults = {a: 1, b: 2, c: 3}
// USE:
const myX = new X({a: 45, b: 32});
myX.method()
// > state: a: 45, b: 32, c: 3 factory functionconst X = (props = {}) => {
// create object (equivalent to a class's 'this')
const x = {
...X.defaults,
...props,
method () {
// do something
console.log(`state: a: ${x.a}, b: ${x.b}, c: ${x.c}`)
}
// ... more methods ...
}
// constructor area
// ...nothing to do here...
// return object as if it would be a class instance
return x
}
// static defaults
X.defaults = {a: 1, b: 2, c: 3}
// USE:
const myX = X({a: 45, b: 32});
myX.method()
// > state: a: 45, b: 32, c: 3 now super condensed const X = (props = {}) => (props = {
...X.defaults,
...props,
method () {
console.log (`state: a: ${props.a} b: ${props.b} c: ${props.c}`)
}
})
X.defaults = {a: 1, b: 2, c: 3} moveable.js as a factory functionimport * as _ from './../lib/utils';
export default function Moveable(opt) {
const M = {
// Assign default values
options: Object.assign({
lockX: false,
lockY: false,
onchange: () => 0
}, opt),
_tapstart(evt) {
_.on(document, ['mouseup', 'touchend', 'touchcancel'], M._tapstop);
_.on(document, ['mousemove', 'touchmove'], M._tapmove);
// Trigger move
M.trigger(evt);
// Prevent default touch event
evt.preventDefault();
},
_tapmove(evt) {
const element = M.options.element;
const b = M.wrapperRect;
let x, y;
if (evt) {
const touch = evt && evt.touches && evt.touches[0];
x = evt ? (touch || evt).clientX : 0;
y = evt ? (touch || evt).clientY : 0;
// Reset to bounds
if (x < b.left) x = b.left;
else if (x > b.left + b.width) x = b.left + b.width;
if (y < b.top) y = b.top;
else if (y > b.top + b.height) y = b.top + b.height;
// Normalize
x -= b.left;
y -= b.top;
} else if (M.cache) {
x = M.cache.x;
y = M.cache.y;
} else {
x = 0;
y = 0;
}
if (!M.options.lockX)
element.style.left = (x - element.offsetWidth / 2) + 'px';
if (!M.options.lockY)
element.style.top = (y - element.offsetHeight / 2) + 'px';
M.cache = {x, y};
M.options.onchange(x, y);
},
_tapstop() {
_.off(document, ['mouseup', 'touchend', 'touchcancel'], M._tapstop);
_.off(document, ['mousemove', 'touchmove'], M._tapmove);
},
trigger(evt) {
M.wrapperRect = M.options.wrapper.getBoundingClientRect();
M._tapmove(evt);
},
update(x = 0, y = 0) {
M._tapmove(new MouseEvent('mousemove', {
clientX: M.wrapperRect.left + x,
clientY: M.wrapperRect.top + y
}));
},
destroy() {
_.off([M.options.wrapper, M.options.element], 'mousedown', M._tapstart);
_.off([M.options.wrapper, M.options.element], 'touchstart', M._tapstart, {
passive: false
});
}
}
M.wrapperRect = M.options.wrapper.getBoundingClientRect();
_.on([M.options.wrapper, M.options.element], 'mousedown', M._tapstart);
_.on([M.options.wrapper, M.options.element], 'touchstart', M._tapstart, {
passive: false
});
return M;
} |
Reminds me of the Java-Factory-Pattern :D. Basically a very clean style, and can be better minified! |
Okay, (finally) I've borrowed it :) |
Instead of using classes, consider using factory functions instead because then there would be no need for
new
and also by avoiding the use ofthis
one would eliminate the need for_.bindClassUnderscoreFunctions(this);
completely.Overall should you consider using factory functions it may actually simplify the codebase and improve the code's portability as functions require no backwards transpilation to ES5 while at the same time improving composability by avoiding
this
and working only with plain objects instead of class instances.No need to make everything a factory function but for something like the
new Selectable();
helper it could be an improvement.This is what the
selectable.js
helper would look likeNote: changing this file in the codebase as it stands to the above code will not be breaking as calling
new (function () {})
does not cause an error.Perhaps read this article from Eric Elliott for more information on factory functions.
The text was updated successfully, but these errors were encountered: