深入理解this、call、apply、bind

call、apply、bind作用是改变函数执行时的上下文,就是改变函数运行时的this指向

一、this

this关键字是函数运行时自动生成的一个内部对象,只能在函数内部使用,总指向调用它的对象。this在函数执行过程中,this一旦被确定了,就不可以在更改。

1、this默认绑定

  • 全局环境中,内部使用this关键字,指向Window对象
var name = "Tong"
function person(){
    return this.name
}
console.log(person())   //Tong

只有函数运行在非严格模式下,默认绑定才能绑定到全局对象

2、this隐式绑定

  • 对象方法中,this指这个上级对象
function test(){
    console.log(this.x)
}
var obj = {}
obj.x = 1
obj.m = test

obj.m()   //1

函数中包含多个对象,尽管这个函数是被最外层的对象所调用,this指向的也是它的上一级对象

var o = {
    a : 10
    b:{
        fn : function(){
                console.log(this.a)  //undefined
                }
            }
        }
    o.b.fn()

3、new绑定

通过构建new关键字生成一个实例对象,此时这个this指向这个实例对象

function fn(){
   console.log(this) //指向obj
  this.user = "xxx"
  }
var obj = new fn()
obj.user //xxx

4、箭头函数中

箭头函数不绑定this,箭头函数中的this指向它所定义的位置,即定义箭头函数的作用域的this指向谁,this就指向谁

setTimeout(() => {
    console.log(this)  //window
   }, 100)

5、显示修改

apply()、call()、bind()可以用来改变函数的调用对象,第一个参数表示改变后的调用这个函数的对象

二、call、apply、bind

1、call()方法

call 方法的第一个参数是this指向,后面传入的是一个参数列表,改变this指向后原函数会立即执行,且此方法只是临时改变this指向一次

function fn(...args){
    console.log(this,args)//{myname:'Tong'}  [1,2]
}
let obj ={
    myname : "Tong"
}
fn.call(obj,1,2)  //this会变成传入的obj,传入的参数必须是一个数组
fn(1,2)   //[1,2]  this指向window

fn.call(null,[1,2]) //this指向window
fn.call(undefined,[1,2]) //this指向window

实现call 

Function.prototype.myCall = function(context){

    if(typeof this !=='Function'){
        throw new Error("not function!")
    }
  context = window||context
    context.fn = this
    let args = Array.from(arguments).slice(1)
    let result = context.fn(...args)
    delete context.fn
    return result
} 

2、 apply()方法

apply接受两个参数,第一个参数是this的指向,第二个参数是函数接受的参数,以数组的显示传入,改变this指向后原函数立即执行。且此方法只是临时改变this指向一次

function fn(...args){
    console.log(this,args)//{myname:'Tong'}  [1,2]
}
let obj ={
    myname : "Tong"
}
fn.apply(obj,1,2)  //this会变成传入的obj,传入的参数必须是一个数组
fn(1,2)   //[1,2]  this指向window

fn.call(null,[1,2]) //this指向window
fn.call(undefined,[1,2]) //this指向window

实现apply() 

 Function.prototype.myApply = function(context){
           if(typeof this !== 'Function'){
               throw TypeError('not function!')
           }
           context = context || window
           context.fn = this
           if(arguments[1]){
             let result = context.fn(...arguments[1])
           }else{
               result = context.fn()
           }
           delete context.fn
           return result

       }

3、bind()方法

bind方法与call很相似,第一个参数是this指向,后面传入的也是一个参数列表(参数列表分多次传入),改变this后不会立即执行,而是返回一个永久改变this指向的函数 


function fn(...args){
    console.log(this,args)//{myname:'Tong'}  [1,2]
}
let obj ={
    myname : "Tong"
}
const bindfn = fn.apply(obj)  //this会变成传入的obj,bind不是立即执行
bindfn(1,2) //this指向obj
fn(1,2)   //[1,2]  this指向window

 

实现bind()

       Function.prototype.myBind = function (context){
            if(typeof this !== 'function'){
                throw new TypeError("error")
            }
            //获取参数
            const args = [...arguments].slice(1)
            const fn = this
            return Fn(){
                //根据调入方式,传入不同的绑定值
                return fn.apply(this instanceof Fn? new fn(...arguments):context,args.concat(...arguments))
            }
        }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值