this指向
标准函数:this 指向调用该函数的上下文对象。
箭头函数:this 引用的是定义箭头函数的上下文。
示例(标准函数):
var a = "window.a";var obj = {a: "window.obj.a",fn() {console.log(this.a);}};obj.fn(); // window.obj.a
示例(箭头函数):
var a = "window.a";var obj = {a: "window.obj.a",fn: () => {console.log(this.a);}};obj.fn(); // window.a
注意:
全局上下文中,this 指向的是 window。但在 严格模式 下,全局上下文中 this 指向的会是 undefined
使用 call、apply、bind 替换 this 指向
我们先提供一个需求:
var hong = {name: "小红",intro(age, from) {console.log("姓名:", this.name);console.log("年龄:", age);console.log("来自:", from);}};var wang = {name: "老王"};hong.intro(15, "北京"); // 姓名:小红 年龄:15 来自:北京
来自上海的30岁的老王,也想做个自我介绍。但是他并没有 intro 方法。因此他只能找小红借该方法。把其中的 this 指向自己,通过传参得出年龄和来源地区。
这时候我们就需要用到 call、apply、bind 了。其中 call、apply 比较相像,bind比较特殊。
call
使用:fn.call(obj, 参数1, 参数2, ..., 参数n) 。
| 参数 | 描述 |
|---|---|
| obj | 要调用该函数的上下文对象 |
| 参数1 | fn 函数本身需要的第 1 个参数 |
| 参数2 | fn 函数本身需要的第 2 个参数 |
| … | |
| 参数n | fn 函数本身需要的第 n 个参数 |
使用 call 帮助老王:
hong.intro.call(wang, 30, '上海') // 姓名:老王 年龄:30 来自:上海
apply
使用:fn.call(obj, [参数1, 参数2, ..., 参数n]) 。
| 参数 | 描述 |
|---|---|
| obj | 要调用 fn 函数的上下文对象 |
| [参数1, 参数2, …, 参数n] | 以数组的形式,传入 fn 函数本身所需要的所有参数 |
使用 apply 帮助老王:
hong.intro.apply(wang, [30, '上海']) // 姓名:老王 年龄:30 来自:上海
bind
bind 跟前两个方法有些不同。它不立即执行函数,而是返回一个已绑定好新 this 的函数,后续可多次调用。
使用:var newFn = fn.bind(obj, 参数1, 参数2, ..., 参数n)
| 参数 | 描述 |
|---|---|
| obj | 要调用 fn 函数的上下文对象 |
| 参数1 | fn 函数需要的第 1 个参数(作为默认值,且后续无法覆盖),非必填。 |
| … | |
| 参数x | fn 函数需要的第 x 个参数(作为默认值,且后续无法覆盖),非必填。 |
| 返回值 | 描述 |
|---|---|
| newFn | 返回一个原函数的拷贝,并拥有指定的 this 和 初始参数 |
它接收参数的形式跟 call 比较相似,但功能上有很大的区别,bind可以有两种用法:
- 仅传入第一个参数(要调用fn函数的上下文对象): ```javascript var myIntro = hong.intro.bind(wang);
myIntro(30, ‘上海’); // 姓名:老王 年龄:30 来自:上海 myIntro(40, ‘深圳’); // 姓名:老王 年龄:40 来自:深圳
只传入第一个参数时,可以在后续调用新函数时传入原函数所需要的参数。2. bind 时就传入原函数需要的参数:```javascriptvar myIntro = hong.intro.bind(wang, 30, '上海');myIntro(); // 姓名:老王 年龄:30 来自:上海myIntro(40, '深圳'); // 姓名:老王 年龄:30 来自:上海
若在使用 bind 时传入了 fn 函数本身所需的参数。那么后面调用时无需再传入原函数所需的参数。且后续调用时无法覆盖这些参数。
