JavaScript this,callee和caller篇
1.this
(1)函数预编译过程,this 指向 window,比如说
function test(c){
var a = 123;
function b(){
}
}
test(1);
在函数预编译的时候,其实 AO 里真正的内容是这样的:
AO{
a:undefined,
b:function b(){},
c:1, arguments:[1],
this:window
}
这里边比以前讲的多两个东西,一个就是实参列表 arguments,这个肯定是有的,如果没有的话你怎么能访问到呢?在一个就是 this,这个 this 假如说我们没有 new 的话, 它是指向 window 的,如果在底下 new test(),那就会隐式的在函数里 var this = Object.create(test.prototype)(这是标准写法),那这个 this 就会把前边的 this 覆盖掉,但是没 new 的话就是指向 window。试验一下:
function test(){
console.log(this);
}
test();
此时就输出
Window{
postMessage: ƒ,
blur: ƒ,
focus: ƒ,
close: ƒ,
frames: Window,
…
}
你在全局访问 window 也得到
Window{
postMessage: ƒ,
blur: ƒ,
focus: ƒ,
close: ƒ,
frames: Window,
…
}
(2)全局作用域里 this 也指向 window
你在全局访问 this 也得到
Window{
postMessage: ƒ,
blur: ƒ,
focus: ƒ,
close: ƒ,
frames: Window,
…
}
(3)call/apply 可以改变函数运行时的 this 指向。
(4)obj.func ();function 函数里的 this 指向 obj。
var obj = {
a:function(){
console.log(this.name)
},
name:'abc'
}
obj.a();
此时就输出 abc,就是谁调用的 this 就是谁,obj 调用的 this 就是 obj,如果是函数自己执行 this 就是 window.
2.callee、caller
(1)arguments.callee
这个 arguments.callee 指的就是函数的引用,也就是它自己,比如说:
function test(){
console.log(arguments.callee);
}
test();
此时就得到 ƒ test() {console.log(arguments.callee);} ,假如你在函数里 console.log(arguments.callee == test);那就得到 true。
用处:比如说我们要初始化一个非常复杂的数据,求 20 的阶乘,那么就用递归来求, 写一个立即执行函数,然后在外部 var 一个 num 来接受它:
var num = (function (n) {
if(n == 1){
return 1;
}
return n * arguments.callee(n - 1);
}(20))
此时访问 num 就得到 2432902008176640000,这里用递归的话,他必须调用自身才可以递归,但是立即执行函数连名字都没有,就用 arguments.callee 来表示它自己。
(2)function.caller
这个 caller 是函数自己的属性,比如说:
function test() {
demo();
}
function demo() {
console.log(demo.caller);
}
test();
这个 caller 是代表了函数的被调用者,demo 是 test 调用的,那么就输出 ƒ test() {demo();}。