首页 前端知识 js中call、apply、bind使用上的一些总结

js中call、apply、bind使用上的一些总结

2024-06-26 23:06:26 前端知识 前端哥 369 21 我要收藏

在日常写代码时,我们有时候要更改函数中this的指向,所以我们会经常用到call、apply、bind三个方法,那么他们都什么共同之处,又有什么区别呢?下面我们来总结一下吧!

在总结之前呢,我们先来定义一个对象,用代码的形式来分析,能让我们更清楚直观一下哈

var personObj = {
    name: "mike",
    age: 16,
    sex: "boy",
    favorite: "football",
    introduce: function(){
        console.log("my name is " + this.name + ", i am " + this.age +         " 岁" )
    },
    myFavorite: function(sex, favorite){
        this.sex = sex;
        this.favorite = favorite;
        console.log("I am a " + this.sex + ", my favorite sport is " + this.favorite)
    }
}

我们在上面定义了一个对象,然后我们将上面的introduce方法在不同的作用域下分别执行一下

personObj.introduce(). // my name is mike, i am 16 岁
let introduce = personObj.introduce
var name = "lucy"
var age = 18
introduce(). // my name is lucy, i am 18 岁

我们可以通过以上运行结果指导,this的指向与函数执行的作用域有关,它在什么作用域下执行,this就指向谁.所以,我们在personObj下调用introduce,它里面的this自然就指向personObj

然后,我们将personObj.introduce赋值给了一个变量introduce,这个变量是在全局下面定义的,所以,当我们执行introduce(),它里面的this就应该指向window

我们在全局作用域下定义了name、age变量,就相当于定义了window.name和window.age, 此时this.name和this.age自然就是全局变量了呀

对上面我们都已经很清楚了哈,那和我们本文开始提到的call、apply、bind又有什么关系呢?当然有关系,我们就是想用他们来更换函数执行中的this呢

下面我们来定义另一个对象

let obj2 = {
	name: 'jhon', 
	age: 28, 
	sex: 'man', 
	favorite: 'pingpang'
}

可以看到这个对象上面并没有introduce的方法,但是我们在这里想要得到一个和personObj对象上introduce一样的效果,我们要怎么做呢?

这就回归到本文开始了,使用call、apply、bind方法来更改函数执行中this的指向,下面我们分别来说,在这之前,我们先来看看函数的结构

console.dir(introduce)

在这里插入图片描述
我们通过上面的结构可以看到,每个函数的原型都有一个apply,bind,call属性,下面我们分别来总结一下他们的使用规则吧

  • call

官网解释: Function 实例的 call() 方法会以给定的 this 值逐个提供的参数调用该函数。

语法: call(thisArg)

introduce.call(obj2). // my name is jhon, i am 28 岁

语法: call(thisArg, arg1, arg2, /* …, */ argN)

let myFavorite = personObj.myFavorite
obj2 // {name: 'jhon', age: 28, sex: 'man', favorite: 'pingpang'}
yFavorite.call(obj2, 'girl', 'dance'). // I am a girl, my favorite sport is dance
obj2. // {name: 'jhon', age: 28, sex: 'girl', favorite: 'dance'}

我们通过上面的代码看到,通过call方法,我们可以借用到其他对象上面的函数

传递给call的第一参数thisArg就是是访问借用函数的对象,并且通过传递arg列表,来给this分配新的属性值

这里,我们在用thisArg要特别注意一下:如果函数不处于严格模式,则 null 和 undefined 会被替换为全局对象,我们来运行一段代码

sex. // 'girl'
favorite // 'basketball'
myFavorite.call(null, 'boy', 'football'). // I am a boy, my favorite sport is football
sex. // 'boy'
favorite // 'football'

上面在call传入null作为执行对象的时候会被替换为全局对象,此时传入新的参数列表,全局对象中值也被更新了

  • apply

官网解释: Function 实例的 apply() 方法会以给定的 this 值和作为数组(或类数组对象)提供的 arguments 调用该函数。

语法:
apply(thisArg)
apply(thisArg, argsArray)

下面我们来运行代码看看

obj2. // {name: 'jhon', age: 28, sex: 'girl', favorite: 'dance'}
introduce.apply(obj2). // my name is jhon, i am 28 岁
myFavorite.apply(obj2, ['boy', 'basketball']). // I am a boy, my favorite sport is basketball
obj2. // {name: 'jhon', age: 28, sex: 'boy', favorite: 'basketball'}

我们看到,在使用上apply和call都可以达到一样的效果,更改执行函数的this指向,并且通过传递数组参数来改变执行对象中的属性,他两唯一的区别就是传递参数的类型上面,apply是一个数组

特别注意: 如果函数不处于严格模式,apply中null 和 undefined 也会被替换为全局对象。 这里不再代码演示了,有兴趣的可以自己执行一遍代码加深印象哈

  • bind

官方描述: Function 实例的 bind() 方法创建一个新函数,当调用该新函数时,它会调用原始函数并将其 this 关键字设置为给定的值,同时,还可以传入一系列指定的参数,这些参数会插入到调用新函数时传入的参数的前面。

语法:
bind(thisArg)
bind(thisArg, arg1, arg2, /* …, */ argN)

返回值:使用指定的 this 值和初始参数(如果提供)创建的给定函数的副本。

此处,需要特殊注意的是,使用bind方法的时候,他会返回一个使用指定的 this 的新的函数,而不是像call和apply那样立马执行

下面,我们来使用bind来运行代码看看

let newMyFavorite =  myFavorite.bind(null, 'boy', 'football')
newMyFavorite
//newMyFavorite是一个函数: ƒ (sex, favorite){
        this.sex = sex;
        this.favorite = favorite;
        console.log("I am a " + this.sex + ", my favorite sport is " + this.favorite)
    }
newMyFavorite()  //I am a boy, my favorite sport is football

我们通过上面代码看到指向bind方法后,会返回一个带有新的this指向的函数,而并不会立马执行.

而且在指向bind方法的时候参数可以在创建新的函数时候提供,也可以在指向新函数的时候在提供

以上就是call、apply、bind的一些总结

转载请注明出处或者链接地址:https://www.qianduange.cn//article/13604.html
标签
评论
发布的文章

JSON、Ajax

2024-07-27 22:07:31

JsonNode、ObjectNode和ArrayNode

2024-07-27 22:07:30

大家推荐的文章
会员中心 联系我 留言建议 回顶部
复制成功!