js中错综复杂的上下文对象this

上下文对象

首先我们通过以下一个简单的例子来说明上下文对象的使用情况:

var info = {
  name:"信息对象",
  fn:function () {
    console.log(this.name);
  }
}

var test ={
  name:"老李头"
};

test.getName = info.fn;

info.fn();//信息对象
test.getName();//老李头

  我们知道,函数中的this指的是被调用函数运行时的上下文环境,而上下文对象指的就是函数体中的this,它的作用是在函数体内引用调用它的对象本身。我们依据这个原则来分析一下上边这段代码:调用info.fn()时,被调用函数fn()的从属对象是info;而当把info.fn赋值给test.getName变量上后,在执行test.getName()后,this指针指向了test对象。顺着这个思路,我们来看一下下边这段代码:

var info = {
  name:"信息对象",
  fn:function () {
    console.log(this.name);
  }
}

var test ={
  name:"老李头"
};

test.getName = info.fn;

var name="全局变量";
var fn = info.fn;


info.fn();//信息对象
test.getName();//老李头
fn();//全局变量 此时依赖对象为window

  综上我们可以说:使用不同的引用来调用同一个函数时,this永远是这个引用所属的对象

改变上下文对象

事实上,函数与对象的从属关系,只有在函数被调用时才体现出来!我们在实际的开发过程中,经常会遇到一个对象调用另外一个对象的成员函数的现象。处理方法有很多。call和apply就是用不同的对象作为上下文对象来调用函数,也就是我们平时所说的改变this的指向问题

call 和 apply

call 和 apply 的功能是一致的,两者细微的差别在于 call 以参数表来接受被调用函的参数,而 apply 以数组来接受被调用函数的参数。call 和 apply 的语法分别是:

被调用函数.call(上下文对象,参数1,参数2,参数3……);

被调用函数.apply(上下文对象,[参数1,参数2,参数3……])

 话不多说,通过下边一段代码我们来理解一下call的工作原理:

var person= {
  name:"老李头",
  tell:function (txt) {
   console.log(this.name+" says: "+txt)
  }
}
var lee = {
  name:"henyulee"
}

person.tell.call(lee,"hello world!");//henyulee says: hello world!

bind

上边说过,可以通过call和apply来绑定上下文对象,但是每次使用都会把上下文作为参数传递,这样会很麻烦,那么有没有一劳永逸的办法呢?我们可以使用bind方法来永久的绑定调用函数的上下文对象

通过下边一段代码来理解一下bind的使用场景:

var person = {
  name:"老李头",
  fn:function (job) {
    console.log(this.name+"是一个:"+job);
  }
}

var user1 = {
  name:"henyulee"
};

user1.fn= person.fn;

user1.fn("北漂");//henyulee是一个北漂

user1.fn = person.fn.bind(person,"前端开发");
user1.fn();//老李头是一个:前端开发

var getJob = person.fn.bind(person,"思想漫步者");
getJob();//老李头是一个:思想漫步者

  我们来解读一下上边这段代码:首先user1.fn直接赋值为person.fn,调用user1.fn()时,此时this指向的是引用fn的user1对象,所以我们拿到的是:henyulee。当用bind方法时,将person作为this指针绑定到user1.fn和getJob2个被调用函数上。所以得到的是person的属性信息。

bind的参数绑定

在使用bind绑定上下文对象时,要注意其参数的传递和之前不太一样,如果参数过多不想一次性传递完整,可以分开传递。

var love = {
  act:"love",  
  fn:function (man,woman) {
    console.log(man +" "+this.act+" "+ woman);
  }
}

var user = love.fn.bind(love,"Romeo");
user("Juliet");//Romeo love Juliet

 观察上边代码,我们不难看出,我们可以把那些参数值固定的首先传递,后续有不一样的参数,作为单独传递即可。这样可以提高开发效率,较少冗余代码!

bind的原理

首先看下边这段代码:

var love = {
  act:"love",  
  fn:function (man,woman) {
    console.log(man +" "+this.act+" "+ woman);
  }
}

var person ={
  act:"hate"
}

person.fn = love.fn.bind(person,"Romeo","Juliet");

person.fn();//Romeo hate Juliet

var fn = person.fn.bind(love);
fn();//Romeo hate Juliet

  person.fn通过love.fn.bind方法将this绑定到了person,调用时返回person的信息。这个时候我们后悔了,想要再绑定回去,发现并不是我们理想中的那样,那么问题来了:发生了什么?要想解释这个现象,我们必须了解 bind 方法的原理。

函数.bind = function (self) {
  return this.call(self);
}

  那么我们将上边令我们疑惑的步骤分解如下:

//省略的参数
person.fn = function () {
  return love.fn.call(person)
}

fn = function () {
  person.fn.call(love)
}

  

 

转载于:https://www.cnblogs.com/henyulee/p/8487839.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值