目录
1.this究竟是什么
2.绑定this的方法
3.caller、arguments和callee
1.this究竟是什么
this总是指向一个调用当前属性或方法所在的对象,它在不同的运行环境(属性和方法的调用者)指向的环境(对象)不同,也就是说this的指向是动态的,但是无论this的指向是谁,只要清楚属性和方法的调用者是谁那么this就指向谁。
//在浏览器全局环境下,即window对象下
var print = function(){
console.log(this)
}
print()//this指向Window,因为这是Window对象调用了print方法
//在特定对象的环境下
var o = {
print: function(){
console.log(this)
}
}
o.print()//this指向o,因为这是o对象调用print方法
2.绑定this的方法
this的动态切换,固然为JavaScript创造了巨大的灵活性,但有时,需要把this固定下来,避免出现意想不到的情况。JavaScript提供了call、apply、bind这三个方法,来切换/固定this的指向。
- function.prototype.call()
函数实例的call方法可以指定函数内部this的指向,即函数执行时所在的作用域
var obj = {};
var fn = function(){
return this
}
fn() === this // true
fn.call(obj) === obj // true
fn()执行时所在的作用域是全局环境,所以this是window,而fn.call(obj)则是在对象obj环境下执行的,所以此时的this指向obj。
fn.call(null) === this
fn.call(undefined) === this
fn.call === this
call方法内部的参数如果为空、null和undefined,则默认传入全局对象。
var obj = {};
var add = function(x,y){
return x+y
}
add.call(obj,2,3)
call方法还可以接受多个参数。call的第一个参数就是this所要指向的那个对象,后面的参数则是函数调用时所需的参数。
-
function.prototype.apply()
apply方法的作用与call方法类似,也是改变this指向,然后再调用该函数。唯一的区别就是,它接收一个数组作为函数执行时的参数。
function fn(x,y){
return x+y
}
fn.call(null,1,1)//2
fn.apply(null,[1,1])//2
fn函数本来接受两个参数,使用apply方法以后,就变成可以接受一个数组作为参数。
【注】
结合apply和数组,我们可以写一个小代码找出数组最大或最小元素;
var arr = [3,5,7,10,2,8];
//未利用apply方法
var min = arr[0];
for (var i = 0;i<arr.length;i++){
if(arr[i]< min){
min = arr[i]
}
}
console.log(min)//2
//使用apply方法
Math.min.apply(null,arr)//2
-
function.prototype.bind()
bind方法用于将函数体内的this绑定到某个对象,然后返回一个新函数,原理和call方法类似。
3.caller、callee和arguments
-
caller
当函数outer调用函数inner时,被调用的函数inner会自动生成一个caller属性,指向调用它的函数对象。
如果该函数未被调用或是不是被其他函数调用,则caller为null。
function outer(){
console.log(outer.caller);
function inner(){
console.log(inner.caller);
};
inner()
}
outer()
//null
//function outer(){}
- arguments
在函数被调用时,会在该函数内部生成一个名为arguments的类数组的隐藏对象,可以使用[]运算符获取函数调用时传递的实参,只有函数被调用时,arguments对象才会创建。
function fn(a,b){
console.log(arguments);
}
fn(1,2)//[1,2]
-
callee
当函数被调用时,它的arguments.callee对象就会指向自身,由于arguments在函数被调用时才有效,因此arguments.callee在函数未调用时是不存在的。
function fn(){
console.log(arguments.callee());
}
fn()//fn(){}
【注】
本次笔记整理自阮一峰JavaScript标准参考教程和饥人谷笔记