call()、apply()、bind() 都是用来重定义 this 这个对象的!

var obj1 = {
  username: "HuiTaiLang",
  fn: function() {
    concole.loh(this);
    console.log(this.username);
  }
}
var obj2 = obj1.fn;
obj2(); //undefined

我们想打印对象 obj2 里面的 username 却打印出来 undefined 是怎么回事呢?如果我们直接执行 obj2.fn()是可以的。

var obj1 = {
  username: "HuiTaiLang",
  fn: function() {
    console.log(this);
    console.log(this.username);
  }
}
obj1.fn();   //HuiTaiLang

能够打印是因为,第一个打印里面的 this 指向全局window,第二个打印里面的 this 指向 obj1 。

虽然这种方法可以达到打印username目的,但是如果我们需要将对象保存到另外的一个变量中,那么就可以通过以下方法。

call

var obj1 = {  
  username: "HuiTaiLang",
  fn: function() {
    console.log(this)    
    console.log(this.username);  
  }
}
var obj2 = obj1.fn;
obj2.call(obj1); // HuiTaiLang

通过在 call 方法,第一个参数就是要添加的 obj1环境中,简单来说,this就会指向那个对象。

call 方法除了第一个参数以外还可以添加多个参数,如下:

var obj1 = {  
  username: "HuiTaiLang",
  fn: function(num1, num2) {
    console.log(num1 + num2); 
    console.log(this.username);  
  }
}
var obj2 = obj1.fn;
obj2.call(obj1, 2, 3); // 5

apply

apply方法和call方法有些相似,它也可以改变this的指向。

var obj1 = {  
  username: "HuiTaiLang",
  fn: function() {
    console.log(this.username);  
  }
}
var obj2 = obj1.fn;
obj2.apply(obj1);   // HuiTaiLang

同样apply也可以有多个参数,但是不同的是,第二个参数必须是一个数组,如下:

var obj1 = {  
  username: "HuiTaiLang",
  fn: function(num1, num2) {
    console.log(num1 + num2); 
    console.log(this.username);  
  }
}
var obj2 = obj1.fn;
obj2.apply(obj1, [2, 3]);   // 5

注意:如果call和apply的第一个参数写的是null,那么this指向的是window对象。

var obj1 = {  
  username: "HuiTaiLang",
  fn: function() {
    console.log(this);  
  }
}
var obj2 = obj1.fn;
var obj3 = obj1.fn;
obj2.call(null); // window
obj3.apply(null); // window

bind

bind和call、apply方法不同,实际上bind方法返回的是一个修改过后的函数。

var obj1 = {  
  username: "HuiTaiLang",
  fn: function() {
    console.log(this.username);  
  }
}
var obj2 = obj1.fn;
obj2.bind(obj1);

var newFn = obj2.bind(obj1);
console.log(newFn);
newFn();

我们会发现 bind 并没有被打印,而我们打印 newFn 打印出的是一个函数,并且可以正常执行。

同样bind也可以有多个参数,并且参数可以执行的时候再次添加,但是要注意的是,参数是按照形参的顺序进行的。

var obj1 = {  
  username: "HuiTaiLang",
  fn: function(num1, num2) {
    console.log(num1 + num2);
    console.log(this.username);  
  }
}
var obj2 = obj1.fn;
var newFn1 = obj2.bind(obj1, 2, 3);
var newFn2 = obj2.bind(obj1);
newFn1();
newFn1(2, 3);

总结:

call 、bind 、apply 都可以用来改变上下文中的 this。这三个函数的第一个参数都是 this 的指向对象,后面的参数:

  • call 的参数是直接放进去的,后面的参数全都用逗号分隔。
  • apply 的所有参数,都必须放在一个数组里面传进去。
  • bind 除了返回是函数以外,它的参数和 call 一样。

当然,三者的参数不限定是 string 类型,允许是各种类型,包括函数 、 object 等等!

call、apply 和 bind的更多相关文章

  1. JS核心系列:浅谈 call apply 与 bind

    在JavaScript 中,call.apply 和 bind 是 Function 对象自带的三个方法,这三个方法的主要作用是改变函数中的 this 指向,从而可以达到`接花移木`的效果.本文将对这 ...

  2. Javascript中call,apply,bind方法的详解与总结

    在 javascript之 this 关键字详解 文章中,谈及了如下内容,做一个简单的回顾: 1.this对象的涵义就是指向当前对象中的属性和方法. 2.this指向的可变性.当在全局作用域时,thi ...

  3. JS中call、apply、bind使用指南,带部分原理。

    为什么需要这些?主要是因为this,来看看this干的好事. box.onclick = function(){ function fn(){ alert(this); } fn();}; 我们原本以 ...

  4. Javascript中call、apply、bind函数

    javascript在函数创建的时候除了自己定义的参数外还会自动新增this和arguments两个参数 javascript中函数也是对象,call.apply.bind函数就是函数中的三个函数,这 ...

  5. 图解call、apply、bind的异同及各种实战应用演示

    一.图解call.apply.bind的异同 JavaScript中函数可以通过3种方法改变自己的this指向,它们是call.apply.bind.它们3个非常相似,但是也有区别.下面表格可以很直观 ...

  6. js里function的apply vs. bind vs. call

    js里除了直接调用obj.func()之外,还提供了另外3种调用方式:apply.bind.call,都在function的原型里.这3种方法的异同在stackoverflow的这个答案里说的最清楚, ...

  7. JS之apply,call,bind区别

    为了加深对基础知识的理解,今天再复习下js中的apply,call,bind的区别和用法.整理笔记的过程也是一个再次学习的过程. apply和call js中的调用apply和call方法可以改变某个 ...

  8. JavaScript中call、apply、bind、slice的使用

    1.参考资料 http://www.cnblogs.com/coco1s/p/4833199.html   2.归结如下 apply . call .bind 三者都是用来改变函数的this对象的指向 ...

  9. JS中的控制函数调用:call(),apply()和bind()

    所有的函数都具有call(),apply()和bind()方法.它们可以在执行方法的时候用一个值指向this,并改变面向对象的作用域. apply方法: 以下的两种表达式是等价的: func(arg1 ...

  10. JS中的call、apply、bind方法

    JS中的call.apply.bind方法 一.call()和apply()方法 1.方法定义 call方法: 语法:call([thisObj[,arg1[, arg2[,   [,.argN]]] ...

随机推荐

  1. CentOs7.6配置邮件服务并发送邮件

    1.使用Yum 来安装依赖包 yum -y install sendmail yum -y install mailx 2.获取授权码 下面以腾讯为例 https://service.mail.qq. ...

  2. Vuex 状态管理的工作原理

    Vuex 状态管理的工作原理 为什么要使用 Vuex 当我们使用 Vue.js 来开发一个单页应用时,经常会遇到一些组件间共享的数据或状态,或是需要通过 props 深层传递的一些数据.在应用规模较小 ...

  3. 21个实用便利的PHP代码

    转载请注明来源:https://www.cnblogs.com/hookjc/ 1. PHP可阅读随机字符串 此代码将创建一个可阅读的字符串,使其更接近词典中的单词,实用且具有密码验证功能. /*** ...

  4. Posix 信号

    转载请注明来源:https://www.cnblogs.com/hookjc/ 函数sem_open创建一个新的有名信号灯或打开一个已存在的有名信号灯.有名信号灯总是既可用于线程间的同步,又可以用于进 ...

  5. 常用汉字大全:汉字读音表GB2312版(共7809个汉字)

    转载请注明来源:https://www.cnblogs.com/hookjc/ 常用汉字:a1:阿啊呵腌吖锕a2:啊呵嗄a3:啊呵a4:啊呵ai1:哀挨埃唉哎捱锿ai2:呆挨癌皑捱ai3:矮哎蔼霭嗳a ...

  6. chmod以数字形式改变文件权限

    Linux文件的三种身份和四种权限,三种身份分别为: u:文件的拥有者 g:文件所属的群组 o:其他用户 对于每个身份,又有四种权限,分别为: r:读取文件的权限(read) w:写入文件的权限(wr ...

  7. DHCP原理与LINUX下的配置

    DHCP原理与LINUX下的配置 目录 DHCP原理与LINUX下的配置 一.DHCP工作原理 1.DHCP概述 2.DHCP的优势 3.DHCP的分配方式 (1)自动分配 (2)手动分配 (3)动态 ...

  8. 泛型、Junit

    一. 泛型 1.泛型的好处 **1)编译时,检查添加元素的类型,提高了安全2)减少了类西较换的次数,提高效率 不使用泛型Dog -> Object -> Dog //放入到ArrayLis ...

  9. asp.core 同时兼容JWT身份验证和Cookies 身份验证两种模式

    在实际使用中,可能会遇到,aspi接口验证和view页面的登录验证情况.asp.core 同样支持两种兼容. 首先在startup.cs 启用身份验证. var secrityKey = new Sy ...

  10. 记录netcore一次内存暴涨的坑

    项目用到了Coldairarrow/EFCore.Sharding: Database Sharding For EFCore (github.com)这个组件,最初是因为分表做的还不错所以用了它. ...