开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第2天,点击查看活动详情
相信学过前端的大佬们,都知道call、apply、bind是干啥的吧?不会吧、不会真的有人不知道吧(手动狗头,阴阳怪气一秒钟)
众所周知,这三种方法都是改变我们函数中的this指向的,为了唤醒回忆,那我在这里先举三个例子帮大家复习一下
//定义一个对象,对象中挂载一些属性
let obj = {
name: "夹心啊",
age: 18,
type: "美女",
};
var name = "Alice";
function foo(num1, num2) {
console.log(this.name);
console.log(this.age);
console.log(this.type);
console.log(num1 + num2);
}
foo(1,2)
猜猜输出什么?是时候考验一下你的this指向有没有学好了!
看看结果
你答对了吗??
好,我们来分析一下输出结果,首先我们要明白的知识点是foo里面this指向是什么?好了,可能又有宝子们不太了解,那还能怎么办,继续讲解!
this绑定
默认绑定
-
this 所处得词法作用域在哪里生效了,this 就绑定了在哪里
-
单独使用 this,它指向全局(Global)对象
-
在严格模式下,全局对象无法进行默认绑定,所以导致 this 只能绑定在 undefined 上
隐式绑定规则
- 当函数引用有上下文对象时, 隐式绑定就会把函数调用中的这个 this 绑定到这个上下文对象,即谁调用谁就是爹
隐式丢失
- 当隐式绑定的函数丢失了绑定对象,就会应用默认绑定
显示绑定规则
- apply bind call 可以强行指定函数的 this 指向
所以很显然,上面的foo函数是在全局下调用的,命中默认绑定,所以它的this指向的就是我们全局,而我们全局作用于下只定义了一个name,却没有age和type,所以当然输出的分别是Alice、Undefined、Undefined和传入相加的数字3咯。
那如果我们在obj内挂载一个foo属性让它等于外部的foo函数,再调用会输出什么呢?
obj.foo=foo
obj.foo(1,2)
foo的this指向了obj,这显而易见了,是命中了隐式绑定规则谁调用谁是this的爹
难度升级👀 通过上面一番赋值操作,obj里面应该有个foo了且内部逻辑和外部foo函数一模一样
let obj = {
name: "夹心啊",
age: 18,
type: "美女",
foo:function(num1, num2) {
console.log(this.name);
console.log(this.age);
console.log(this.type);
console.log(num1 + num2);
}
};
是这样毫无疑问吧。
那如果我将obj中的foo再赋给一个变量,调用该变量了呢
var test=obj.foo
//调用foo发生什么?
test(1,2)
看看结果
嗯?怎么会这样???为什么foo中的this指向了全局??你现在肯定是满脸黑人问号,这个foo不是在obj里面吗,为什么还指向了全局??
停停停,咱们的foo是在obj里面没错,但是宝子,问题来了!你没调用啊!你只是把foo这个函数又从obj里面拿到了外面在全局下调用了,属于典型的隐式丢失了。
举个例子,foo是个手电筒,obj调用foo相当于你晚上在家里把手电筒打开了,手电筒只能照亮你家,照不到外面。但是你出去散步,你把手电筒从家里带出来了,你在外面把手电筒打开,手电筒还能照亮你家吗?当然不能啦!!它现在只能照亮野外的路。
那明白了上面几点,那我们使用call、apply、bind这样来搞一下,分别输出什么呢?
foo.call(obj,1,2)
foo.apply(obj,[1,2])
var newFoo=foo.bind(obj)
newFoo(1,2)
看看结果
好家伙!谁看了不惊呼一句好家伙,三个都集体输出了obj对象的属性,说明call、apply、bind这三个方法集体改变了foo()里面原本的this指向,把它强行掰弯到了obj的身上了
接下来是个小扩展
箭头函数中的this
通常来说箭头函数是没有自己的this的,它的this继承上下文的this
定义在全局作用域下的箭头函数
毫无疑问依旧输出全局作用域下的name即Alice
定义在作用域中的箭头函数
那如果我在普通函数中定义一个计时器,计数器回调为箭头函数
var objfun = function () {
this.name = "夹心啊";
this.age = 18;
this.type = "美女";
setTimeout(() => {
console.log(this.name);
});
};
objfun()
调用objfun()定时器会输出什么呢
显然箭头函数集成到了objfun内部的this输出了"夹心啊"
讲明白了this的原理,下一篇我们来看看如何实现call、apply、bind吧