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.
3.142.199.184