my code is:
var length = 20;
function fn(){
console.log(this.length);
}
var o = {
length:10,
e:function (fn){
fn();
arguments[0]();
}
}
o.e(fn);
the output is 20,1
,who can tell me why?
When the this
keyword occurs inside a function, its value depends on how the function is called.
In your case, fn()
is called without providing the a this value, so the default value is window
.
With arguments[0]()
, the context is the arguments
object, whose length is 1
.
The point is it does not matter where the function is called, but it matters how the function is called.
var length = 20;
function fn(){
console.log(this.length);
}
var o = {
length:10,
e:function (fn){
fn(); // this will be the window.
arguments[0](); // this will be arguments object.
}
}
o.e(fn);
Further more, if you want this
to be the object o
, you could use call
or apply
, or bind
an object first.
var length = 20;
function fn(){
console.log(this.length);
}
var o = {
length:10,
e:function (fn){
var fn2 = fn.bind(this);
fn.call(this); // this in fn will be the object o.
fn.apply(this); // this in fn will be the object o.
fn2(); // this also will be the object o.
}
}
o.e(fn);
Let's expand your code a little bit:
var length = 20;
function fn() {
console.log(this, this.length);
}
var o = {
length: 10,
e: function(fn) {
fn();
fn.call(this);
arguments[0]();
}
}
o.e(fn);
Demo: http://jsfiddle.net/ambiguous/Ckf2b/
Now we can see what this
is (and thus where this.length
comes from) when fn
is called. This gives me the following output:
DOMWindow 0
Object 10
[function fn() { console.log(this, this.length); }] 1
We also have three ways of calling the function fn
:
fn()
: just call it like any old function.fn.call(this)
: Use call
to force a specific context (AKA this
).arguments[0]()
: Call fn
through the arguments
object.When you say fn()
, there is no explicit value of this
anywhere in sight so, in a browser, you get window
as your this
. The global window
happens to have a length
property:
Returns the number of frames (either frame or iframe elements) in the window.
That's where the zero (in my output) comes from, your window.length
may be different.
We call e
as o.e(fn)
so this
inside e
is o
, that's what o.e(...)
means (barring bound functions and related complexities). So the this
in fn.call(this)
is o
and that makes fn.call(this)
the same (more or less) as o.fn = fn; o.fn()
and we get o
and 10
in the console. Notice that dot showing up again?
fn.call(o)
is likeo.fn = fn; o.fn()
The third one, arguments[0]()
, contains a hidden dot as p = 'm'; o[p]
is (more or less) the same as o.m
so arguments[0]()
is like fn = arguments[0]; arguments.fn = fn; arguments.fn()
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With