1.this和arguments
在函数内部,有两个特殊的对象:arguments和this。
arguments:包含着传入函数中的所有参数。arguments有一个callee属性,该属性是一个指针,指向拥有这个arguments对象的函数。
this:引用的是函数据以执行的环境对象(作用域)。
caller属性:保存着调用当前函数的函数(父函数)的引用。
arguments.callee等同于使用其的函数名。在递归算法中,使用arguments.callee代替函数名,可以消除函数耦合带来的隐患。
耦合:简单地说,软件工程中对象之间的耦合度就是对象之间的依赖性。对象之间耦合越高,维护成本越高。因此对象的设计应使类与构件之间的耦合最小。(百度百科:耦合)
实例:
window.color = "red";var o = {color:"blue"};function sayColor(){ alert(this.color);}sayColor(); //"red"o.sayColor = sayColor;o.sayColor(); //"blue"
在调用函数之前,this的值并不确定,this可能会在代码执行过程中引用不同的对象。当在全局作用域中调用sayColor()时,this引用的是全局对象window;当把这个函数赋给对象o并调用o.sayColor()时,this引用的是对象o。
function outer(){ inner();}function inner(){ alert(inner.caller); //inner可以用arguments.callee代替}outer(); //显示outer()函数源代码
outer()调用了inner(),所以inner.caller就指向outer()。
2.apply(),call(),bind()
每个函数都包含两个非继承而来的方法:apply()和call(),两者用途都是在特定的作用域中调用函数,他们能够改变函数赖以运行的作用域。bind()是ECMAScript中定义的方法。这个方法会创建一个函数的实例,其this值会被绑定到传给bind()函数的值。
实例:
window.color = "red";var o = {color:"blue"};function sayColor(){ alert(this.color);}sayColor(); //redsayColor.call(this); //redsayColor.call(window); //redsayColor.call(to); //blue
直接改变作用域的最大好处,就是对象不需要与方法有任何的耦合关系。在前面的例子中,我们先是将sayColor()函数放到对象o中,然后在通过o来调用它的,而在这里重写的例子中,就不需要先前那个多余的步骤了。
window.color = "red";var o = {color:"blue"};function sayColor(){ alert(this.color);}var objectSaycolor = sayColor.bind(o);objectSayColor(); //blue
sayColor调用bind()并传入对象o,创建了objectSayColor()函数。objectSayColor()函数的this值等于o,因此即使在全局作用域中调用这个函数,也会看到“blue”。