@autobind decorator.
This commit is contained in:
parent
a502965d19
commit
5c1611c484
@ -1,3 +1,57 @@
|
|||||||
|
import bind from 'lodash.bind'
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
|
||||||
|
const {defineProperty} = Object
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
|
||||||
|
// See: https://github.com/jayphelps/core-decorators.js#autobind
|
||||||
|
export function autobind (target, key, {
|
||||||
|
configurable,
|
||||||
|
enumerable,
|
||||||
|
value: fn,
|
||||||
|
writable
|
||||||
|
}) {
|
||||||
|
return {
|
||||||
|
configurable,
|
||||||
|
enumerable,
|
||||||
|
|
||||||
|
get () {
|
||||||
|
const bounded = bind(fn, this)
|
||||||
|
|
||||||
|
defineProperty(this, key, {
|
||||||
|
configurable: true,
|
||||||
|
enumerable: false,
|
||||||
|
value: bounded,
|
||||||
|
writable: true
|
||||||
|
})
|
||||||
|
|
||||||
|
return bounded
|
||||||
|
},
|
||||||
|
set (newValue) {
|
||||||
|
if (this === target) {
|
||||||
|
// New value directly set on the prototype.
|
||||||
|
delete this[key]
|
||||||
|
this[key] = newValue
|
||||||
|
} else {
|
||||||
|
// New value set on a child object.
|
||||||
|
|
||||||
|
// Cannot use assignment because it will call the setter on
|
||||||
|
// the prototype.
|
||||||
|
defineProperty(this, key, {
|
||||||
|
configurable: true,
|
||||||
|
enumerable: true,
|
||||||
|
value: newValue,
|
||||||
|
writable: true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
|
||||||
// Debounce decorator for methods.
|
// Debounce decorator for methods.
|
||||||
//
|
//
|
||||||
// See: https://github.com/wycats/javascript-decorators
|
// See: https://github.com/wycats/javascript-decorators
|
||||||
|
72
src/decorators.spec.js
Normal file
72
src/decorators.spec.js
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
/* eslint-env mocha */
|
||||||
|
|
||||||
|
import {expect} from 'chai'
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
|
||||||
|
import {autobind, debounce} from './decorators'
|
||||||
|
|
||||||
|
// ===================================================================
|
||||||
|
|
||||||
|
describe('autobind', function () {
|
||||||
|
class Foo {
|
||||||
|
@autobind
|
||||||
|
getFoo () {
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
it('returns a bound instance for a method', function () {
|
||||||
|
const foo = new Foo()
|
||||||
|
const {getFoo} = foo
|
||||||
|
|
||||||
|
expect(getFoo()).to.equal(foo)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('works with multiple instances of the same class', function () {
|
||||||
|
const foo1 = new Foo()
|
||||||
|
const foo2 = new Foo()
|
||||||
|
|
||||||
|
const {getFoo: getFoo1} = foo1
|
||||||
|
const {getFoo: getFoo2} = foo2
|
||||||
|
|
||||||
|
expect(getFoo1()).to.equal(foo1)
|
||||||
|
expect(getFoo2()).to.equal(foo2)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
|
||||||
|
describe('debounce', function () {
|
||||||
|
let i
|
||||||
|
|
||||||
|
class Foo {
|
||||||
|
@debounce(1e1)
|
||||||
|
foo () {
|
||||||
|
++i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
i = 0
|
||||||
|
})
|
||||||
|
|
||||||
|
it('works', function (done) {
|
||||||
|
const foo = new Foo()
|
||||||
|
|
||||||
|
expect(i).to.equal(0)
|
||||||
|
|
||||||
|
foo.foo()
|
||||||
|
expect(i).to.equal(1)
|
||||||
|
|
||||||
|
foo.foo()
|
||||||
|
expect(i).to.equal(1)
|
||||||
|
|
||||||
|
setTimeout(function () {
|
||||||
|
foo.foo()
|
||||||
|
expect(i).to.equal(2)
|
||||||
|
|
||||||
|
done()
|
||||||
|
}, 2e1)
|
||||||
|
})
|
||||||
|
})
|
Loading…
Reference in New Issue
Block a user