Strange Function Behavior with Prototype and Event Listeners - JavaScript

时间:2017-12-02 00:31:48

标签: javascript oop javascript-events prototypejs

Original Modal

I want to use a universal app object. To this empty object I will add functions as needed. The issue is that some functions will need to all others within the app object.

So, my question is: how do I construct a large object without having to define all functions inside the object at the time of creation? I would like to split up the chunks of code to not have one astronomical long .js file.

There is a simple example of my original code:

var app = {
  tow: function () {
    return true;
  },
  one: function () {
    return this.tow();
  }
};

// app.one() => returns true

Updated Modal

Here is something I found interesting. I was playing around with the prototype modal and discovered something strange. When I use this model I can add functions that can call other added functions. But, when I create an event listener it is unable to run the code. Can anyone explain why this is?

Modified code with unexpected result:

function modal () {}

modal.prototype.one = function () {
  return this.two();
};

modal.prototype.two = function () {
  return "cool";
};

modal.prototype.init = function () {
  document.getElementById('go')
    .addEventListener("click", this.one);
}

var app = new modal();
app.init();

// app.one() => returns true
// event listener => returns "TypeError: this.two is not a function"

JSBIN: https://jsbin.com/vureruziza/edit?js,console,output

3 个答案:

答案 0 :(得分:0)

this.one调用你所做的是指addEventListener函数,而不是你的对象。这将解决问题

modal.prototype.init = function () {
  var self = this;
  document.getElementById('go')
    .addEventListener("click", function(){
      self.one()
    });
}

答案 1 :(得分:0)

将click函数与此绑定,导致函数需要此上下文,而不是窗口上下文。然后在de click handler中调用this.one函数。

function modal () {}

modal.prototype.one = function () {
  return this.two();
};

modal.prototype.two = function () {
  return "cool";
};

modal.prototype.init = function () {
  document.getElementById('go')
   .addEventListener("click", function(e){ 
      console.log(this.one()) 
    }.bind(this));
    
/*
The following wil also be called but your return value 
of your this.one function won't be captured. But your code will run.

    .addEventListener("click", this.one.bind(this));
    
Try replacing it with the above and put a debugger statement in this.one 
and see that the code will actualy be ran, just not captured to output.
*/
}

var app = new modal();
app.init();

// app.one() => returns true
// event listener => returns "TypeError: this.two is not a function"
<div id="go">go</div>

答案 2 :(得分:0)

使用ES6胖箭头功能。更新modal.prototype.init,如下所示 -

modal.prototype.init = function () {
  document.getElementById('go')
    .addEventListener("click", () => this.one());
}

修改 - 如果您想调试此问题,您可以console.log this函数one中的modal.prototype.one = function () { console.log(this); return this.two(); }; 值 -

window

您很可能会看到modal对象。你当然不会看到public abstract class AsyncCommand<T> { public ObservableEmitter<T> mSubscriber; public ObservableEmitter<T> getSubscriber() { return mSubscriber; } public abstract T run() throws Exception; public Observable<T> returnObservable() { return Observable.create( new ObservableOnSubscribe<T>() { @Override public void subscribe(ObservableEmitter<T> subscriber) throws Exception { mSubscriber = subscriber; try { subscriber.onNext(run()); subscriber.onComplete(); } catch (Exception e) { subscriber.onError(e); } } } ).subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()); } } 对象。