Search code examples
rubycoffeescriptthisprototypeextend

CoffeeScript extend operator modifying 'this'?


I recently stumbled over something. I wanted to add the ability to remove an object from an array like this:

someArray.remove(element)

I wanted to use the extend operator of CoffeeScript and do it the following:

Array::remove = (element) ->
  return false unless _.include(this, element)
  this = this.splice(_.indexOf(this, element), 1)
  true

But the prototype function, that is created points this to the Array object itself, so the only way is to return something, which would look like this:

someArray = someArray.remove(element)

and the implementation for that like this:

Array::remove = (element) ->
  return this unless _.include(this, element)
  this.splice(_.indexOf(this, element), 1)

In ruby this is the exact difference between join and join!.

Is there any way to achieve this?


Solution

  • I think you are mistaken about splice. It operates on the array itself. This seems to do the trick, unless I completely misunderstood your question:

    _ = require "underscore"
    
    Array::remove = (element) ->
      index = _.indexOf @, element
      return false if index is -1
      @splice index, 1
      true
    
    foo = ["a", "b", "c"]
    console.log foo            # => ['a', 'b', 'c']
    console.log foo.remove "b" # => true
    console.log foo            # => ['a', 'c']
    console.log foo.remove "d" # => false
    console.log foo            # => ['a', 'c']
    

    Note that coffeescript includes a shim for indexOf, so underscore is not strictly needed, so you could do:

    Array::remove = (element) ->
      index = @indexOf element
      return false if index is -1
      @splice index, 1
      true