JS 中的函数调用
看到留言说,很多童靴不理解为什么 例 6 的 innerFunction 和 例 7 的 this 是指向 window 的,所以我就来补充一下 JS 中的函数调用。
例 6:
例 7:
|
|
函数调用的方法一共有 4 种
- 作为一个函数调用
- 函数作为方法调用
- 使用构造函数调用函数
- 作为函数方法调用函数(call、apply)
作为一个函数调用
比如上面的 例 1:
例 1:
|
|
这样一个最简单的函数,不属于任何一个对象,就是一个函数,这样的情况在 JavaScript 的在浏览器中的非严格模式默认是属于全局对象 window 的,在严格模式,就是 undefined。
所以说更多的情况是将函数作为对象的方法使用。比如例 2:
例 2:
这里定义一个对象 a,对象 a 有一个属性(name)和一个方法(fn)。
然后对象 a 通过 . 方法调用了其中的 fn 方法。
然后我们一直记住的那句话“this 永远指向最后调用它的那个对象”,所以在 fn 中的 this 就是指向 a 的。
使用构造函数调用函数
如果函数调用前使用了 new 关键字, 则是调用了构造函数。
这看起来就像创建了新的函数,但实际上 JavaScript 函数是重新创建的对象:
|
|
这就有要说另一个面试经典问题:new 的过程了,(ಥ_ಥ)
这里就简单的来看一下 new 的过程吧:
伪代码表示:
- 创建一个空对象 obj;
- 将新创建的空对象的隐式原型指向其构造函数的显示原型。
- 使用 call 改变 this 的指向
- 如果无返回值或者返回一个非对象值,则将 obj 返回作为新对象;如果返回值是一个新对象的话那么直接直接返回该对象。
所以我们可以看到,在 new 的过程中,我们是使用 call 改变了 this 的指向。
作为函数方法调用函数
在 JavaScript 中, 函数是对象。
JavaScript 函数有它的属性和方法。
call() 和 apply() 是预定义的函数方法。 两个方法可用于调用函数,两个方法的第一个参数必须是对象本身
在 JavaScript 严格模式(strict mode)下, 在调用函数时第一个参数会成为 this 的值, 即使该参数不是一个对象。
在 JavaScript 非严格模式(non-strict mode)下, 如果第一个参数的值是 null 或 undefined, 它将使用全局对象替代。
这个时候我们再来看例 6:
例 6:
|
|
这里的 innerFunction() 的调用是不是属于第一种调用方式:作为一个函数调用(它就是作为一个函数调用的,没有挂载在任何对象上,所以对于没有挂载在任何对象上的函数,在非严格模式下 this 就是指向 window 的)
然后再看一下 例 7:
例 7:
这个简单一点的理解可以理解为“匿名函数的 this 永远指向 window”,你可以这样想,还是那句话this 永远指向最后调用它的那个对象,那么我们就来找最后调用匿名函数的对象,这就很尴尬了,因为匿名函数名字啊,笑哭,所以我们是没有办法被其他对象调用匿名函数的。所以说 匿名函数的 this 永远指向 window。
如果这个时候你要问,那匿名函数都是怎么定义的,首先,我们通常写的匿名函数都是自执行的,就是在匿名函数后面加 () 让其自执行。其次就是虽然匿名函数不能被其他对象调用,但是可以被其他函数调用啊,比如例 7 中的 setTimeout。