JsFunction and the this keyword

The this keyword refers to the current instance of a class in Dart and never changes once the class object is instantiated. Generally, we should omit the this keyword and use it only if we have name conflicts between the class members and function arguments or variables. In JavaScript, the this keyword refers to the object that owns the function and behaves differently compared to Dart. It mostly depends on how a function is called. We can't change the value of this during function execution and it can be different every time the function is called. The call and apply methods of Function.prototype were introduced in ECMAScript 3 to bind any particular object on the value of this in the call of these methods:

fun.call(thisArg[, arg1[, arg2[, ...]]])
fun.apply(thisArgs[, argsArray])

While the syntax of both these functions looks similar, the fundamental difference is that the call method accepts an argument list while the apply method accepts a single array of arguments.

All the functions in JavaScript inherit the call and apply methods from Function.prototype, so both the methods invoke the original function and assign the first argument to the value of the this keyword permanently so it cannot be overridden.

The following bind method of Function.prototype was introduced in ECMAScript 5:

fun.bind(thisArg[, arg1[, arg2[, ...]]])

This method creates a new function with the same body and scope as the original function, but the this keyword is permanently bound to the first argument of the bind function, regardless how the function is being used. The call and bind methods can solve the issues we face while changing the this keyword. Let's take a look at how we can do this with the following JavaScript code:

this.name = 'Unknown';

function sendMessage(message) {
  console.log('Send message: ' + this.name + ' ' + message);
}

function DieselEngine() {
  this.name = 'Diesel';
}

sendMessage('engine started'),

var engine = new DieselEngine()

var dieselLog = sendMessage.bind(engine);
dieselLog('engine started'),

The invocation of the sendMessage function results in the following console log:

Send message: Unknown engine started

The sendMessage function prints a message on the console with the Unknown name because this references the global object in the web browser. Then, we create an instance of Engine and bind the sendMessage function to engine. The bind method creates a new function dieselLog with the same body, but the this keyword is permanently bound to engine. So, when you call the dieselLog function, it uses the name from DieselEngine and prints the following message:

Send message: Diesel engine started

If we need to use the Dart version of sendMessage instead of the original one, we can use JsFunction instantiated with the withThis constructor of the JsObject class to call the function with the value of this passed as the first argument:

import 'dart:js' as js;

void main() {
  js.context['sendMessage'] = new 
    js.JsFunction.withThis(otherSendMessage);
  
  js.JsFunction DieselEngine = js.context['DieselEngine'];
  js.JsObject engine = new js.JsObject(DieselEngine);
  
  js.JsFunction sendMessage = js.context['sendMessage'];
  sendMessage.apply(['engine started'], thisArg: engine);
}

otherSendMessage(self, String message) {
  print('Message sent: ' + self['name'] + ' ' + message);
}

First, we assigned Dart's otherSendMessage function to JavaScript's sendMessage function. The named constructor withThis creates a JavaScript function pattern and uses the reference on otherSendMessage instead of func in all the future calls:

function () {
   return func(this, Array.prototype.slice.apply(arguments));   
}

So, when we call the apply method of sendMessage, the JavaScript function calls the original otherSendMessage function. It passes the engine object to the self parameter of the otherSendMessage function and passes the engine started string in the message parameter. The result is printed to the web console:

Send message: Unknown engine started
Send message: Diesel engine started
Message sent: Diesel engine started

Bear in mind that the type of parameter self of the otherSendMessage function depends on the value passed as the second argument of the apply method of sendMessage instance.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.142.199.184