Hitesh Kumar
Hitesh Kumar

Reputation: 3698

Is Javascript bind is call by value?

I am learning bind, call and apply functions. I am using bind to set callback for the api calls. Here are my functions:

function errorCallback(list, error) {
      $log.error('Somehting went wrong while loading json.');
      $log.log(list, error);
    }

    function successCallback(list, response) {
      $log.info('JSON loaded successfully.');
      //$log.log(list, response);
      //this works 
      //$scope.list = list.concat(response.data);
      //this doesn't
      list = list.concat(response.data);
      $log.log($scope.list, list);
    }

This is how I am binding them:

var successCb = successCallback.bind(null, $scope.list),
      errorCb = errorCallback.bind(null, $scope.list);

When I use them as callback:

$scope.loadJson = function() {
      $http.get('data.json').then(successCb, errorCb);
    };

They are getting invoked properly. But the concern is that when I update list , it does not update the actual parameter which is passed. I want to know that when we bind the parameters for bind, are they bound using value or reference? Here's the plunkr.

Upvotes: 0

Views: 58

Answers (2)

Thalaivar
Thalaivar

Reputation: 23642

Function.prototype.bind does the same thing as call or apply, but does not call the function right away instead it returns a new function with your parameters bound to this and when the function is called from a new scope or context, it will remain same.

Binding also allows you to prevent your constructors from being "hacked" by apply or call since it will always use the binded parameters for this no matter what someone sends to attempt to override this via call or apply.

If you have noted, the last one does not change from guest to rajini even though we try to override it via call.

function Profile(u) {
    this.user = u;
    this.getUser = function () {
        return this.user;
    };
}

var x = new Profile('guest');

alert(x.getUser.apply({
    user: 'Vinoth'
})); // Vinoth
alert(x.getUser.call({
    user: 'Google'
})); // Google
alert(x.getUser.bind(x).call({
    user: 'Rajini'
})); // guest

A fiddle to play around. https://jsfiddle.net/5qxpn4v0/

Upvotes: 1

Bergi
Bergi

Reputation: 665286

Everything in JavaScript is passed by value. Some of these values can be references to mutable things (objects - also called reference values), but that's it. When you reassign to list, nothing is changing but the list variable in your local scope. You actually would need to mutate your array, which concat doesn't do - use push instead.

If you want to mutate the $scope, you will need to pass it itself and explicitly assign its .list property.

Upvotes: 4

Related Questions