Reputation: 105
.call
, .apply
, .bind
methods of Function.prototype
don't work for functions once defined as methods of Vue instance in .vue
file.
I'm using @vue/cli
project, compiled with vue-cli-service serve
.
Here's reduced example of code, which can be placed in any Vue single-file component definition.
methods: {
foo() {
console.log(this);
}
},
created() {
this.foo.call({ bar: 42 });
this.foo.apply({ bar: 42 });
this.foo.bind({ bar: 42 })();
}
Expected output to the console is triple { bar: 42 }
, since this
value was changed for these calls.
However, VueComponent
object is printed to the console.
I checked these methods for overloading, using
this.foo.bind === Function.prototype.bind // returns true
,
they are not overloaded.
It may be caused by Vue using Proxy
objects or even by templates compilation.
Simplest @vue/cli
project with code above will be enough to reproduce the problem.
Thanks
Upvotes: 4
Views: 959
Reputation: 222309
Vue component methods are bound to the context, which is component instance. This could be checked with:
function foo() {
foo() {
console.log(this);
}
}
...
methods: { foo },
created() {
this.foo !== foo // true
}
...
this.foo.bind === Function.prototype.bind
check isn't representative since this.foo
is regular function, so it inherits bind
.
Once a function is bound, it cannot be re-bound or be called with different context:
const context = {};
const boundFoo = (function foo() { return this; }).bind(context);
// boundFoo.call({}) === context
// boundFoo.bind({})() === context
It isn't a good practice to rely on arbitrary dynamic this
context in JS OOP. If a method needs a context, it should be provided to it as an argument:
methods: {
foo(ctx) {
console.log(ctx);
}
},
created() {
this.foo({ bar: 42 });
}
Or be shared as instance property, depending on the purpose.
Upvotes: 3