TL;DR
this
is determined when a function is executed. this
will use implicit function execution
context. If we don’t use explicit function execution, or invoke the methods on an object, then this
in the function is bound to the global object. In the method invocation, this is the object that owns the method. We also can explicitly bind a function’s execution context to an object use call
or apply
What are you talking about
Ok…… At first, I don’t know what the TL;DR
part means. Does the this
in JS are the same as self
in Ruby language? Umn… Short answer is, yap, it is similar, but this
are more ways to use it.
Let’s review the self
in Ruby
if you are in your terminal, you go into irb, then type puts self
, it will show you that
main
=> nil
if you type console.log(this)
in the chrome dev tools console:
Window {speechSynthesis: SpeechSynthesis, caches: CacheStorage, localStorage: Storage, sessionStorage: Storage, webkitStorageInfo: DeprecatedStorageInfo…}
Good, in this part this
in JS global object is the same as ruby’s self
in main object.
How about we create the same object in JS and Ruby
class Phone
def initialize
@owner = 'you'
@brand = 'Samsung'
@system = 'Android'
end
def ring
puts self
puts "Hello, World"
end
end
mine = Phone.new
# mine
# => #<Phone:0x00000001594740 @owner="you", @brand="Samsung", @system="Android">
mine.ring
# <Phone:0x00000001594740>
# Hello, World
# => nil
In JS:
function say() {
console.log(this);
console.log('hello, world');
};
var phone = {
owner: 'you',
brand: 'Samsung',
system: 'Android',
ring: say,
}
phone.ring();
//Object {onwer: "you", brand: "Samsung", system: "Android"}
// hello, world
It is similar here, if we create an object, then `this` points to the object. What if like we want to use another phone?
var anotherPhone = {
onwer: 'Peter',
brand: 'Apple',
system: 'iOS',
}
Because JS is not like classic OOP, You cannot create another object from the mold(class). Although, it has some similar way(prototype) that you can work like a classic OOP. But let’s assume that we want this anotherPhone
to use the phone.ring()
; How could we do this?
phone.ring.call(anotherPhone);
//or
say.call([anotherPhone]);
That’s the difference between Ruby and JS. `this` in JS is determined when a function is executed, not like Ruby, self
is determined when defined.
And if you want to store to a variable, whenever you call this function, you always give you the anotherPhone
. How about to deal with it?
var anotherRing = phone.ring.bind(anotherPhone);
anotherRing();
//Object {onwer: "Peter", brand: "Apple", system: "iOS"}
//hello, world
Even you call this anotherRing
in the window
, the global object of JS, it is still give you this
is the anotherPhone
.
So, JS’s method in an object, it will change `this` depending on when you execute it. Not like Ruby, No matter when you execute, it will give you the same self
, the object itself. But this
in JS will change.
We make a little different about the phone object
:
var phone = {
owner: 'you',
brand: 'Samsung',
system: 'Android',
ring: function() {
function bell() {
console.log(this);
}
console.log('hello, world');
return bell();
},
}
phone.ring();
//hello, world
// Window {speechSynthesis: SpeechSynthesis, caches: CacheStorage, localStorage: Storage, sessionStorage: Storage, webkitStorageInfo: DeprecatedStorageInfo…}
Umm, what happen? this
now is global window
.
Remember in the very first beginning:
this
is determined when a function is executed.this
will useimplicit function execution
context.
SO, the inner function inside the phone.ring() method, it use implicit function execution. It points to global. We can change it to this,
var phone = {
owner: 'you',
brand: 'Samsung',
system: 'Android',
ring: function() {
function bell() {
console.log(this);
}
console.log('hello, world');
return bell.call(this);
},
}
phone.ring();
//hello, world
//Object {owner: "you", brand: "Samsung", system: "Android"}
Yes! this
now points to the phone
object.