Use Ruby self to understand Javascript this

Reading time ~3 minutes

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 use implicit 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.

to_param in Ruby on Rails

If I want a custom slug=======================I walk through this cutstom slug.1. create migration `add_slug` to add a column inside the...… Continue reading

What is ORM in Rails mean?

Published on July 14, 2017