Bootstrap

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

;