资讯专栏INFORMATION COLUMN

JS中this关键字改变指向的三种方法(apply、call、bind)

shiina / 1797人阅读

摘要:函数的几种调用方式普通函数调用作为方法来调用作为构造函数来调用使用方法来调用方法箭头函数但是不管函数是按哪种方法来调用的,都需要记住一点谁调用这个函数或方法关键字就指向谁。作为构造函数来调用构造函数出来的实例,指向这个实例对象。

首先,了解一下this关键字。this关键字就涉及到函数调用的内容。函数的几种调用方式:

1 普通函数调用
2 作为方法来调用
3 作为构造函数来调用
4 使用apply/call方法来调用
5 Function.prototype.bind方法
6 ES6箭头函数

但是不管函数是按哪种方法来调用的,都需要记住一点:谁调用这个函数或方法,this关键字就指向谁。

普通函数调用
var age = 18;
function person(){
    this.name = "Tony";
    console.log(this);      //window
    console.log(this.name); //Tony
    console.log(this.age);  //18
}
person();

代码中定义一个普通函数person,在调用时实际上person是作为全局对象window的一个方法来进行调用的,即window.person();
因此是window对象调用了person方法,那么person函数当中的this即指window,同时window还拥有了另外一个属性name,值为“Tony”。

定义一个全局变量age,它相当于是window的一个属性。在调用person函数时它的this指向window,所以在函数内部可以访问到age变量,这也解释了函数内部可访问全局变量。

作为方法来调用
var person = {
    name : "Tony",
    showName:function(){
        console.log(this.name);
    }
}
person.showName();

var name = "Tom";
var showname = person.showName;
showname();

定义一个对象person包含一个showName的方法,在对象person内调用方法返回的是Tony,显然this指向了对象person。

再定义一个全局变量name,将person.showName方法赋值给变量showname,因为在全局定义的嘛,所以showname也相当于window的一个属性,此时调用showname它的this是指向window的,所以返回的值就是全局变量“Tom”。

var personA = {
    name : "Tony",
    showName:function(){
        console.log(this.name);
    }
}
var personB = {
    name : "Tom",
    sayName:personA.showName
}
personB.sayName();    //Tom

personB对象中的方法调用personA中的方法,虽然showName是personA中定义的,但调用了personB,那this就指向了personB。

作为构造函数来调用
function Person(name){
    this.name = name;
}
var personA = new Person("Tony");
console.log(personA.name);

构造函数new出来的实例,this指向这个实例对象。

下面就来了解一下this指向改变的三种方法。

在JavaScript中,call、apply和bind是Function对象自带的三个方法,这三个方法的主要作用是改变函数中的this指向。所以可知它们的共同点就是都用来改变函数的this对象的指向的;还有就是三者第一个参数都是this要指向的对象,也就是想指定的上下文(函数的每次调用都会拥有一个特殊值——本次调用的上下文(context)——这就是this关键字的值。),然后再利用后续参数传参。而它们的不同也就是传参的不同,bind 是返回对应函数,便于稍后调用;apply 、call 则是立即调用 。

apply()方法 

它接收两个参数,一个是函数运行的作用域(this),另一个是参数数组。

语法:

apply([thisObj [,argArray] ]);

定义:应用某一对象的一个方法,用另一个对象替换当前对象

说明:如果argArray不是一个有效数组或不是arguments对象,那么将导致一个 TypeError,如果没有提供argArray和thisObj任何一个参数,那么Global对象将用作thisObj。

function Person(name){
    this.name = name;
    this.showName = function(){
        console.log(this.name);
    }
}
function Student(name){
    Person.apply(this,arguments);
}
var stu = new Student("Tony");
stu.showName();
call()方法 

它第一个参数和apply()方法的一样,但是传递给函数的参数必须列举出来。

语法:

call([thisObject[,arg1 [,arg2 [,...,argn]]]]);

定义:调用一个对象的一个方法,以另一个对象替换当前对象。

说明: call方法可以用来代替另一个对象调用一个方法,call方法可以将一个函数的对象上下文从初始的上下文改变为thisObj指定的新对象。

thisObj取值的情况:

1 不传,或者传null,undefined, 函数中的this指向window对象
2 传递另一个函数的函数名,函数中的this指向这个函数的引用
3 传递字符串、数值或布尔类型等基础类型,函数中的this指向其对应的包装对象,如 String、Number、Boolean
4 传递一个对象,函数中的this指向这个对象

call方法的一些常见例子:

1.

function add(a,b){
    console.log(a+b);
}
function subtraction(a,b){
    console.log(a-b);
}
add.call(subtraction,3,1);    //4

定义一个加法函数、加法函数,最后的调用语句意思就是用加法替代了减法,在减法函数中通过call方法改变了this的指向,已经不再计算a-b,而是作用加法中的a+b。

2.

function Student(){
    this.name = "Tom";
    this.showName = function(){
        console.log(this.name);
    }
}
function Teacher(){
    this.name = "Tony";
}
var stu = new Student();
var tea = new Teacher();
stu.showName.call(tea);

定义一个学生函数,它有属性name和方法showName,而老师函数只有name属性,最后一个调用语句的意思就是把学生的方法用到了老师函数中执行,即便老师是没有这个方法的。

3.

function Parent(name){
    this.name = name;
    this.showName = function(){
        console.log(this.name);
    }
}
function Son(name){
    Parent.call(this,name);
}
var baby = new Son("Tony");
baby.showName();

Parent.call(this,name)意思就是使用父母这个对象替代掉儿子函数中的this对象,那么这个儿子函数中就可以直接调用父母对象中的属性和方法,这也就是继承。

bind()方法

bind()最简单的用法是创建一个函数,使这个函数不论怎么调用都有同样的this值。

var person = {
    name : "Tony",
    showName : function(){
        console.log(this.name);
    }
}
person.showName();      //Tony

var name = "Tom";
var getName = person.showName;
getName();              //Tom

var boundGetName = getName.bind(person);
boundGetName();         //Tony

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/109664.html

相关文章

  • 如何秒懂 this

    日常开发中经常会遇到 this 指向的 bug,郁闷好久才猛然醒悟,痛定思痛,将 this 做个汇总,以便在日后的开发工作中少走弯路。注:本文讲述只针对浏览器环境。一、全局执行​​showImg(https://segmentfault.com/img/bVbq4NJ?w=277&h=109);可以看出在全局作用域中 this 指向当前的全局对象 Window。二、函数中执行 非严格模式中 ​​s...

    Lin_YT 评论0 收藏0
  • 秒懂 this

    摘要:特殊情况结合定时器调用若在对象的函数中,普通函数作为定时器延时执行的函数调用,指向箭头函数作为定时器延时执行的函数调用,指向定义时所在的对象,也就是中的,即。实例化一个对象如上第四点,作为一个构造函数使用。 日常开发中经常会遇到 this 指向的 bug,郁闷好久才猛然醒悟,痛定思痛,将 this 做个汇总,以便在日后的开发工作中少走弯路。 注意:本文讲述只针对浏览器环境。 一、全局执...

    sumory 评论0 收藏0
  • 前端_JavaScript_面向对象编程

    摘要:面向对象编程对象的原生方法分成两类自身的方法静态方法和的实例方法。的静态方法方法与,参数是对象,返回一个数组,数组的值是改对象自身的所有属性名区别在于返回可枚举的属性,返回不可枚举的属性值。 面向对象编程 Objects对象的原生方法分成两类:Object自身的方法(静态方法)和Object的实例方法。注意Object是JavaScript的原生对象,所有的其他对象都是继承自Objec...

    Blackjun 评论0 收藏0
  • 《javascript高级程序设计》函数调用模式 & this深度理解

    在上一篇文章(《javascript高级程序设计》笔记:Function类型)中稍微提及了一下函数对象的属性—this,在这篇文章中有深入的说明: 函数的三种简单调用模式 1 函数模式 定义的函数,如果单独调用,不将其与任何对象关联,那么就是函数调用模式 function fn(num1, num2) { console.log(this); } // 直接在全局调用 fn();// w...

    wyk1184 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<