@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.
|
||||
//
|
||||
// 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