admin管理员组

文章数量:1025799

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);
}

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);
}
Share Improve this question edited Apr 11, 2013 at 20:24 smockle asked Apr 11, 2013 at 20:17 smocklesmockle 2,32219 silver badges19 bronze badges 7
  • possible duplicate of What is the difference between call and apply? – Andreas Louv Commented Apr 11, 2013 at 20:18
  • 2 Your title doesn't match your question. – Andreas Louv Commented Apr 11, 2013 at 20:20
  • How should I word the title? I'm willing to change it. (Assuming Stack Overflow allows me to; I've never edited a title before). – smockle Commented Apr 11, 2013 at 20:23
  • 1 I changed the title to hopefully better reflect what I'm asking. Sorry for any inconvenience. – smockle Commented Apr 11, 2013 at 20:25
  • 1 There's also bind developer.mozilla/en-US/docs/JavaScript/Reference/… and jQuery's $.proxy(this, ...) – potench Commented Apr 11, 2013 at 20:40
 |  Show 2 more ments

3 Answers 3

Reset to default 7

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/en-US/docs/JavaScript/Reference/Operators/this

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.

I know two ways to do this (shown below).

And as you see, both work :-)

Which one is the best practice?

It depends. Which does fit better in your code structure?

If you're coding very object-orientated and both functions are written in a neighborhood where you expect everything to be a method and the this keyword to reference an object instance everywhere, you should not break that.

If not, you should choose option #1 for simplicity. Also you might want to consider the other formal parameters b has - if the object reference doesn't go in a line with them, option #2 might be better.

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);
}

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);
}
Share Improve this question edited Apr 11, 2013 at 20:24 smockle asked Apr 11, 2013 at 20:17 smocklesmockle 2,32219 silver badges19 bronze badges 7
  • possible duplicate of What is the difference between call and apply? – Andreas Louv Commented Apr 11, 2013 at 20:18
  • 2 Your title doesn't match your question. – Andreas Louv Commented Apr 11, 2013 at 20:20
  • How should I word the title? I'm willing to change it. (Assuming Stack Overflow allows me to; I've never edited a title before). – smockle Commented Apr 11, 2013 at 20:23
  • 1 I changed the title to hopefully better reflect what I'm asking. Sorry for any inconvenience. – smockle Commented Apr 11, 2013 at 20:25
  • 1 There's also bind developer.mozilla/en-US/docs/JavaScript/Reference/… and jQuery's $.proxy(this, ...) – potench Commented Apr 11, 2013 at 20:40
 |  Show 2 more ments

3 Answers 3

Reset to default 7

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/en-US/docs/JavaScript/Reference/Operators/this

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.

I know two ways to do this (shown below).

And as you see, both work :-)

Which one is the best practice?

It depends. Which does fit better in your code structure?

If you're coding very object-orientated and both functions are written in a neighborhood where you expect everything to be a method and the this keyword to reference an object instance everywhere, you should not break that.

If not, you should choose option #1 for simplicity. Also you might want to consider the other formal parameters b has - if the object reference doesn't go in a line with them, option #2 might be better.

本文标签: What is the best way to pass the this pointer in JavaScriptStack Overflow