allow m.withAttr callback to determine it's own this [non-breaking change]

Background:

In ES6 we now have `Object.setPrototypeOf` which makes prototype delegation an alternative to *sugary*, fake class coding patterns. This can be accomplished in ES5, but ES6 is much more elegant. Here is a basic example. `new` is never used and `this` is very easy to follow.

Working example with changes to mithril.js on lines 854, 858, 859 *only*.
http://jsbin.com/nopugo/1/edit?js,console,output

```javascript

'use strict'

const m = require('mithril')

const DataModel = {
    data: [1,2,3],
    getData(){
        console.log('getting data from server')
        return this.data
    },
    postData(val){
        console.log('sending data to server')
        this.data.push(val)
    }
}
const ViewModel = {
    filterEvenData: function() {
        return this.getData().filter((val) => (val % 2 === 0) && (+val !== 0))
    },
    addNewData: function(val){
        console.log('adding new data', val)
        this.postData(val)
    }
}

var Model = Object.setPrototypeOf(ViewModel, DataModel)

const App = {

    controller(){},

    view(ctrl){
        return m('div', [
            m('pre', [ 'EVEN NUMBERS IN DATA\n',
                this.filterEvenData().map((key,i) =>`${i+1} = ${key}\n`)                
            ]),
            m('div', 'Enter a number'),
            m('input[placeholder=number]', {

                // addNewData is called with **this** === undefined unless we pass `this` to Function.prototype.call in m.withAttr
                onchange: m.withAttr('value', App.addNewData, App),
                value: null
                }
            )
        ]) 
    }
}
Object.setPrototypeOf(App, Model)

m.mount(document.body, App)

```
This commit is contained in:
pelonpelon 2015-08-01 14:51:18 -05:00
parent a23a32a3d9
commit 72c039c4dc

View file

@ -851,11 +851,12 @@ var m = (function app(window, undefined) {
else m.endComputation();
}
m.withAttr = function(prop, withAttrCallback) {
m.withAttr = function(prop, withAttrCallback, callbackThis) {
return function(e) {
e = e || event;
var currentTarget = e.currentTarget || this;
withAttrCallback(prop in currentTarget ? currentTarget[prop] : currentTarget.getAttribute(prop));
var _this = callbackThis || this;
withAttrCallback.call(_this, prop in currentTarget ? currentTarget[prop] : currentTarget.getAttribute(prop));
};
};