Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the best way to pass the this pointer in JavaScript?

Tags:

javascript

Say I have two functions in JavaScript, and I want to pass the this pointer from one to the other. I know two ways to do this (shown below). Which one is the best practice?

Option 1:

function a() {
    b(this);
}

function b(elem) {
    alert(elem);
}

Option 2:

function a() {
    b.call(this);
}

function b() {
    alert(this);
}
like image 498
smockle Avatar asked Dec 27 '22 05:12

smockle


2 Answers

This doesn't answer the question, but the title to the question before it was changed:
What is the difference between function.call(this) and function(this) in JavaScript?


The use of call sets the context (this) of the called function:

function foo() {
    console.log(this);
}  

foo(); // window
foo.call({}); // {}

The default context using non strict mode (In a browser envirement) is window showed in the example above.

Non strict mode is the default mode. Strict mode is only supported by some browsers.

If the function is a method of an object the context is the object itself:

var obj = {
    foo: function () {
        console.log(this);
    }
};

obj.foo(); // obj
obj.foo.call({}); // {}

https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/this

like image 94
Andreas Louv Avatar answered Feb 20 '23 15:02

Andreas Louv


There is really no best practice in general, just guidelines. It's strictly depends by the way you're coding. Personally, I would use the first form, it's more functional oriented rather than object oriented, and you avoid an additional operation – changing the contextual object – plus, you will not depends by the context object itself. It means, if you need to reuse b somewhere, you don't have all the time to change it's contextual object.

I'll give you a practical example. Let's say that b is a function that set the style.display of an element to none. Let's call it hide:

function hide(element) {
    element.style.display = "none";
}

You can use it like:

hide(document.getElementById("foo"))

So far so good. But what if you want to hide all elements of a list?

// this is used to have an array of element for the example,
// because NodeList are not Array
var slice = Function.call.bind(Array.prototype.slice);
var nodes = slice(document.getElementsByTagName("div"));

nodes.forEach(hide);

You simple have to pass hide. That's because the callback you pass to forEach, is called passing as first argument each value of the array.

But it's not over yet. Let's say you want to hide not all the div in the list, but only the div in the list that contains a the text "foo".

function hasFoo(element) {
    return element.textContent.indexOf("foo") > -1
}

Then:

nodes.filter(hasFoo).forEach(hide);

And so on. You can really takes advantages of the functional programming aspect and methods of JavaScript, if you decide to pass the "subject" of the function as first argument.

Here you can find the documentation of ES5 methods like filter and forEach.

like image 21
ZER0 Avatar answered Feb 20 '23 15:02

ZER0