简体   繁体   中英

Why is my bound this object being ignored?

I'm trying to call a method from a require d Node module with a specific this object. As far as I see, there are three ways to do this, with .bind(obj)(args) , or with .call(obj, arg1, ...) , or with .apply(obj, aryArgs) . I'm currently using bind , but I have tried all three with identical levels of not-success.

This is where I'm running the call:

var library = require("./library.js");

// ...

requestHandler.bind(library)(req);

requestHandler is a reference to the exported status function from this file:

exports.status = () => {
  console.log(this);
  this.render({text: "status ok"});
};

exports.paramSwitching = () => {
  this.render("rendered via param switching");
};

exports.json = () => {
  this.render({json: {this: 'renders', as: 'json'}});
};

exports.view = () => {
  this.render({view: true, locals: {text: 'hi'}});
};

I'd like this to work so that the status function is called with library as its this object, since that's where render is defined. However, the console.log statement is showing this as the evaluated contents of the file holding status , ie

{ status: [Function],
  paramSwitching: [Function],
  json: [Function],
  view: [Function] }

What's happening here, and how do I fix it? (Or, if I can't because Node is doing something weird, is there a workaround?)

The arrow function itself already binds the this within the function body function to the this of the context it was defined in. So you cannot change the this with any of those methods.

If you need to change the this then you cannot use arrow functions.

Your request handler is declared with arrow notation:

exports.status = () => {
  console.log(this);
  this.render({text: "status ok"});
};

By design the arrow notation captures this at the time the function is declared. It is almost as if you did this:

exports.status = (function(){
  console.log(this);
  this.render({text: "status ok"});
}).bind(this);

This means the status() function is already bound and cannot be rebound. The solution is to stop using arrow functions:

exports.status = function(){
  console.log(this);
  this.render({text: "status ok"});
};

Figured it out right after I posted this question. I've used arrow functions in the file containing status , which do not create their own this scope but use the enclosing context.

Calling bind , call or apply on these functions has no effect because this is already set to the function's enclosing context, which in this case is the eval'd file.

Switching the arrow functions out for regular functions (changing () => to function () ) has fixed the issue.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM