在 JavaScript 的世界里,一切均可以理解为对象。包括函数,函数在 JS 中也是一类对象,不过是一类特殊的对象,将函数做为构造类来使用,能够生成新的对象,从而实现JS 世界中的类的概念。javascript
接下来咱们从头开始回顾函数的发展过程。java
咱们知道,函数包含定义
和调用
两个阶段,函数在使用以前,必须先定义。数组
有的同窗可能更习惯用
声明
来表示定义,不要紧,均可以。app
函数定义共分为以下几种:函数
接下来咱们一一介绍。ui
最先咱们定义一个函数是这样子的,也是最多见的。this
function test(){
//todo
}
复制代码
很简单,定义好以后,咱们就可使用了:spa
test();
复制代码
定义一个函数,也能够理解为定义一个变量,将这个变量的值指向一个函数,因而就有了另一种定义函数的方式(表达式定义):code
var test = function(){
//todo
}
复制代码
调用也很简单对象
test();
复制代码
那声明式定义函数与表达式定义函数之间的区别是什么? 你们看下面两段代码:
test();
function test(){
//todo
}
复制代码
对象方法的调用:
var a = {
say:function(){
//todo
}
}
a.say();
复制代码
函数调用时, 内部的this,必定是指向函数所属的对象的。
var say = new Function('a','b','return a + b');
复制代码
ES6 规范中的函数定义方式。
let say = () => {};
复制代码
let say = function(){console.log(this)}
say();
复制代码
间接调用分为两种,call
和 apply
,call
和 apply
的做用就是改变函数调用的上下文。下面举个例子来讲明一下它们的做用。
咱们先定义一个函数 test:
function test(){
console.log(this);
}
复制代码
这个函数很简单,仅仅是打印当前上下文 this。
咱们这样调用
test();
复制代码
输出结果是 window。
我如今又有一个对象 a :
var a = {
name: '小A'
}
复制代码
我想让a 对象执行 test 方法提供的功能,该怎么办呢?
固然,你们能够说,我给 a 对象增长一个方法 testA,而后执行 a 对象的 testA 方法,不就能够了吗?
a.testA = function(){
console.log(this);
}
a.testA();
复制代码
那咱们若是不想为 a 对象额外增长这个方法,而是复用最开始定义的 test 方法,怎么办?? 这就是 call 和 apply 的做用。
test.call(a);
//或者
test.apply(a);
复制代码
这就是改变函数执行上下文的意思。
call 和 apply 的惟一区别是传参不一样。
call 的第一个参数是上下文对象,剩余的参数就是函数调用时的参数。
test.call(a, 1, 2, 3);
复制代码
apply 的第一个参数是上下文对象,第二个参数是个数组,数组中存放的是函数调用时的参数。
test.apply(a, [1, 2, 3]);
复制代码
var a = {
name: 'A',
say: function(){
console.log(this.name);
}
}
a.say();
复制代码
打印的是 'A'。
咱们接着看:
var a = {
name: 'A',
say: function(){
function test(){
console.log(this.name);
}
test();
}
}
a.say();
复制代码
执行结果是 undefined,而不是 'A'。 这是为何?
一个简单的理解方法:
函数调用时
所指向的对象。test() 等价为 window.test()
因此 test() 执行时 this 指向 window。
定义时
所指向的执行上下文。以上就是对函数 this 指向的一些概括,利用这些方法,能让你精准地判断 this 指向,即便写一百层复杂嵌套函数,也能轻松判断出来。
(本文完)