前言
大家好,我是热爱前端的菜鸟luckyCover。
this
this是JavaScript语言的一个
关键字
,它是函数运行时
,内部产生的一个对象
,这个对象只能在函数内部使用
javascript
function test() {
this.x = 1;
}
上边函数运行时,函数内部会自动有一个this对象可以使用。
那么this
的值是什么呢?也就是我们常说的this的指向
。
函数在不同场合下,this
有不同的值。总的来说,this
就是函数运行时所在的环境对象。
分以下几种情况:
情况一:纯粹的函数调用
这是最通常的写法,属于全局调用,因此this
就代表了全局对象。
javascript
let x = 1;
function test() {
console.log(this.x);
};
test(); //1
情况二:作为对象的函数调用
函数还可以作为某个对象的方法调用,这时候this
就指这个上级对象。
javascript
function test() {
console.log(this.x);
};
let obj = {};
obj.x = 1;
obj.m = test;
m(); //1
情况三:作为构造函数调用
所谓构造函数,其实就是new这个函数会产生一个新对象。如果这个函数使用new
调用,this
就指向这个新创建的对象。
javascript
function test() {
this.x = 1;
};
const obj = new test();
console.log(obj.x); //1
运行结果为1,为了证明此时的this
不是全局对象,我们对代码做如下变动:
javascript
let x = 2
function test() {
this.x = 1;
};
const obj = new test();
console.log(x); //2
运行的结果没有变,证明全局变量x
的值根本没变。
情况四:apply调用
apply()
是函数中的一个方法,作用是改变函数的调用对象。它的第一个参数就表示改变调用这个函数的对象。因此,这时候this
的指向就是接收的第一个参数
。
javascript
let x = 0;
function test() {
console.log(this.x);
};
const obj = {};
obj.x = 1;
obj.m = test;
obj.m.apply(); //0
apply()
参数为空,默认调用全局对象。因此这时的运行结果为0,证明this
指向的是全局对象。
如果把最后一行代码修改为:
javascript
obj.m.apply(obj); //1
运行结果就变为1了,证明此时this
指向对象obj
。
根据上边四种情况,我们可以简单总结一下this指向了。
判断this关键字的引用(即指向)是谁的唯一方法就是看this所在的方法在哪里被调用。
接下来,我们介绍下call
、apply
、bind
这三个关键字
call
call
是每个函数都有的一个方法,它允许你在调用某个函数的时候为其指定上下文
。
比如下边这段代码:
javascript
function greet() {
alert(`Hello, my name is ${this.name}`);
};
const user = {
name: 'Tyler',
age: 27
};
greet(); //直接调用,此时this指向的是window,由于window上没有name属性,会输出undefined
根据上边的总结,我们都知道为了判断this
的引用必须查看这个函数的调用位置。现在就引出一个问题,上面这段js代码中,如果直接调用greet()
函数,那么此时的this
指向的是全局对象window,然而现在我们要让greet()
方法的调用对象是user
,也就是让this指向user
。这时候就可以用call
方法了。
下面的代码可以实现在调用greet()
方法时使用user
做上下文。
javascript
greet.call(user);
概况一下call属性
:call
是每个函数都有的一个属性,传递给它的第一个参数
会作为调用函数时的上下文
。换句话说,this
会指向传递给它的第一个参数。
apply
apply函数和call函数唯一的不同就是函数的第二个参数。
我们先来看看以.call
调用的例子:
javascript
function greet(lang1, lang2, lang3) {
alert(`Hello, my name is ${this.name} and I know ${lang1}, ${lang2}, and ${lang3}`)
};
const user = {
name: 'Tyler',
age: 27
};
const languages = ['JavaScript', 'Ruby', 'Python'];
greet.call(user, languages[0], languages[1], languages[2]);
使用call
方法调用奏效,它显示了如何将参数传递给.call
调用的函数。不过,这样传递参数显然比较麻烦。如果我们需要传10个参数,那得一个一个在后边传递。幸运的是,apply()
方法可以让我们以数组的形式
传递参数,并且会自动将其展开
。
将上边代码改为使用.apply
来调用:
javascript
const languages = ['JavaScript', 'Ruby', 'Python']
greet.apply(user, languages);
相信看到这里的你已经get到call
和apply
两者的区别了,没错,其实就是第二个参数的传递形式不同
,我们先不进行总结,后边还有一个bind
没看,看完你就能归纳出它们的异同点了。
bind
bind
属性和call完全相同,它不会立即调用函数
,而是返回一个能在以后调用的函数。看下这段代码:
javascript
function greet(lang1, lang2, lang3) {
alert(`Hello, my name is ${this.name} and I know ${lang1}, ${lang2}, and ${lang3}`)
};
const user = {
name: 'Tyler',
age: 27
};
const language = ['JavaScript', 'Ruby', 'Python'];
const newFn = greet.bind(user, languages[0], languages[1], languages[2]);
newFn(); //"Hello, my name is Tyler and I know JavaScript, Ruby, and Python"
看完上边代码,我们可以发现bind
和call
在参数传递
以及调用形式
上是完全相同的,唯一区别就是在bind
等号的左边可以接收一个新函数
(即bind返回的那个函数
),而这个函数正是绑定了this上下文的函数
。
好了,了解完上边三个关键字,我相信你自己都可以做总结了,那我这里还是走完流程吧😊~
总结
对于apply
、call
、bind
三个关键字
相同点:它们的第一个参数都是函数绑定的上下文(即this的指向)
不同点:
call
和apply
:第二个参数传递形式不同,call
中的参数需要逐个传
,而apply
可以以数组的形式传递
。call
和bind
:第一、二个参数完全相同,不同的是bind
会返回一个绑定好上下文的新函数
。
结语
以上就是本篇的所有内容了,如果文章对于你有点用,请留个赞鼓励一下luckyCover嘿嘿,我们下篇文章见!