Last active
December 9, 2016 10:09
-
-
Save synzhang/da981ebff525d6927bfbd23673a14fe4 to your computer and use it in GitHub Desktop.
OLOO(Objects linked to other objects) style delegation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @desc OLOO(Objects linked to other objects) style delegation | |
* @see 《You Don't Know JS》 Chapter 6 | |
*/ | |
const Widget = { | |
width: 50, | |
height: 50, | |
// Constructor | |
init(width, height) { | |
this.width = width || this.width; | |
this.height = height || this.height; | |
this.$elem = null; | |
}, | |
insert($where) { | |
if (this.$elem) { | |
this.$elem.css({ | |
width: this.width + 'px', | |
height: this.height + 'px' | |
}).appendTo($where); | |
} | |
} | |
}; | |
const createButton = function (mixins = []) { | |
// Delegation | |
let Button = Object.create(Widget); | |
let secretNum = 1; | |
Object.assign(Button, { | |
label: 'Default', | |
num: 0, | |
// Suggest different and more descriptive names | |
// to avoid the ugliness of the explicit pseudo-polymorphic calls. | |
setup(width, height, label) { | |
// Delegated call | |
this.init(width, height); | |
this.label = label || this.label; | |
this.$elem = $('<button>').text(this.label); | |
}, | |
build($where) { | |
// Delegated call | |
this.insert($where); | |
this.$elem.click(this.onClick.bind(this)); | |
}, | |
onClick(event) { | |
console.log("Button '" + this.label + "' clicked!"); | |
}, | |
// Privileged function | |
getSecretNum() { | |
return secretNum; | |
} | |
// Concatenative | |
}, ...mixins); | |
return Button; | |
} | |
const canAnimate = { | |
animate() { | |
console.log('Animate!') | |
} | |
} | |
const Button = createButton(); | |
const AnimatedButton = createButton([canAnimate]); | |
$(document).ready(function () { | |
let $body = $(document.body); | |
let btn1 = Object.create(Button); | |
btn1.setup(125, 30); | |
let btn2 = Object.create(AnimatedButton); | |
btn2.setup(150, 40, 'Animate'); | |
btn1.build($body); | |
btn2.build($body); | |
btn2.animate(); | |
console.log(btn1.num); // 0 | |
console.log(btn1.secretNum); // undefined | |
console.log(btn1.getSecretNum()); // 1 | |
console.log(Widget.isPrototypeOf(Button)); // true | |
console.log(Widget.isPrototypeOf(btn1)); // true | |
console.log(Button.isPrototypeOf(btn1)); // true | |
console.log(AnimatedButton.isPrototypeOf(btn2)); // true | |
console.log(Object.getPrototypeOf(btn1) === Widget); // false | |
console.log(Object.getPrototypeOf(btn1) === Button); // true | |
console.log(Object.getPrototypeOf(btn2) === AnimatedButton); // true | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment