PREWORDS
Try to write a downright article to introduce what this
is and how to use it in javascript.
Two misconceptions:
"This" refers to the function itself.
"This" somehow refers to the function's scope.
See the below code:
varcount = 0;
functioncountTool(num) {
console.log(num);
this.count++;
}
countTool.count = 0;
for (vari = 0; i < 2; i++) {
countTool.call(countTool, i);
}
console.log(countTool.count); // 0, 1, 2
console.log(this.count); // 0 [in browser]; undefined [in node]
What "this" is?
From the code above, this
mechanism provides a more elegant way of implicitly "passing along" an object reference, leading to cleaner API design and easier reuse.
CALL-SITE
Two principles:
What's "this"? Call-site is the only thing that matters for "this binding".
What's call-site? It'a a scope where is holding the reference of fun. (所持函数的引用所在的调用域。)
We have a number of rule to apply.
* Implicit binding(ignore strict model)
Example 1
function foo() {
console.log(this.a);
}
var a = "oops, glpbal"
var obj = {
a: 2,
foo: foo
}
var bar = obj.foo;
bar(); // < -- call-site is global
obj.foo(); // < -- call-site is obj
Here we see, in this example, bar
and obj.foo
they both are the reference to function foo
. But they are in different call-site scope. bar
is defined in the global scope and obj.foo
is in the obj
scope instead. So the outcomes are in different manner.
Example 2
function foo() {
console.log(this.a);
}
function doFoo(fn) {
fn(); // < -- call-site
}
var obj = {
a: 2,
foo: foo
}
var a = "oops, glpbal"
doFoo(obj.foo);
In this example, just one stuff need to be noted is fn
is parameter to function doFoo
instead of argument. So the scope of parameter is the same with the function which is belong to.
Another thing you have to be aware of is with "use strict" model in the global scope. As we know, this should point to window object in the global scope. Indeed it do, but we can't pass this into the function we expected. It's like a knid of bug remaining. See the example below. It will show us with error.
function foo() {
"use strict"
console.log(this.a);
}
var a = "oops, glpbal"
foo(); // Error
* explicit binding("new" is a speciality of)
Explicit binding is to provide a kind of approch to leverage apply
, call
or bind
built-in methods to hardcode the this
object to the specific function.
Here we see an example below, in this one, obj
is to be hardcoded to the function foo
. So no matter in any situation, this of foo
is always pointing to obj
object.
function foo(something) {
console.log(this.a, something);
return this.a + something;
}
var obj = {
a: 2,
}
var bar = function () {
return foo.apply(obj, arguments);
}
var b = bar(3); // 2 3
console.log(5); // 5
A word says, the most typical way to wrap a function with a hard binding creates a pass-through of any arguments passed and any return calue received.
硬绑定最典型的方法是为任何传入参数和返回值创建“桥梁”。
How bind
method works? See the code below:
function foo(something) {
console.log(this.a, something);
return this.a + something;
}
// simple bind helper
function bind(fn, obj) {
return function () {
return fn.apply(obj, arguments)
};
}
var obj = {
a: 2,
};
var bar = bind(foo, obj);
var b = bar(3); // 2 3
console.log(5); // 5
* new
operation is not common use, but this will show you another area to this
binding.
Let check the code below:
function foo(something) {
this.a = something;
}
var obj = {};
var bar = foo.bind(obj); // 2
bar(2);
console.log(obj.a); // Here is to make explicit binding happen
var baz = new bar(3);
console.log(obj.a); // 2
console.log(baz.a); // 3 Here is to use new operation, this is in the highest priority
new
operation is in the highest priority of all rules. Here we see.
new
operation has done 4 steps when it is invoked.
- A brand new object is created(aka constructed) out of thin air.(凭空,无中生有)
- The newly constructed object is [[Prototype]]-linked.
- The newly constructed object is set as the this binding for that function call.
- Unless the function returns its own alternate object, the new-invoked function call will automatically return the newly constructed object.