call、apply、bind的区别及应用

本文介绍了call、apply、bind的作用,即改变函数运行时的this指向。阐述了它们之间的区别,call和apply改变this后执行函数,bind返回改变上下文后的函数,且call和apply在参数传递上有差异。还说明了它们在项目中的应用,如将伪数组转化为数组、数组拼接、判断变量类型、实现继承等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

let obj = {name:"cyy"};

function Child(name){
    this.name = name;
}

Child.prototype = {
    constructor:Child,
    showName:function(){
        console.log(this.name);
    }
}

var child = new Child("kiruthika");

child.showName(); //kiruthika

// call,apply,bind使用
child.showName.call(obj)
child.showName.apply(obj)
let bind = child.showName.bind(obj) //返回一个函数
bind() // cyy

bind方法是事先把fn的this改变为其我们提供想要的结果,并且把对应的参数值准备好,以后要用到了,直接的执行即可,也就是说bind同样可以改变this的指向,但和apply、call不同就是不会马上执行

  • call、apply与bind的区别

call和apply改变了函数的this上下文后便执行该函数,而bind则是返回改变了上下文后的一个函数。

  • call、apply的区别

call与apply存在与参数的差别,call和apply的第一个参数都是要改变上下文的对象,而call从第二个参数开始以参数列表的形式展现,apply则是把除了改变上下文对象的参数放在一个数组里面作为他的第二个参数

let arr = [1,3,5,24,6];
console.log(Math.max.call(null,1,3,5,24,6))//24
console.log(Math.max.call(null,arr))//NAN
console.log(Math.max.apply(null,arr))//24 apply可以直接用数组arr传递进去
function fn(){
	console.log(this)
}

fn.call()// 普通模式下this是window,在严格模式下this是undefined
fn.call(null)// 普通模式下this是window,在严格模式下this是null
fn.call(undefined)// 普通模式下this是window,在严格模式下this是undefined
 

项目应用:
将伪数组转化为数组(含有length属性的对象,dom节点,函数的参数arguments)

js中的伪数组具有length属性,并且可以通过0,1, 2…下标来访问其中的元素,但是没有Array中的push、unshift等方法。就可以利用call、apply来转化成真正的数组,就可以使用其数组中的方法了

<div class="content">1</div>
<div class="content">2</div>
<div class="content">3</div>

以下写法不适用于IE6-8 , 会报错:Array.prototype.slice:‘this’ 不是 Javascript对象

let contents = document.getElementsByClassName("content");
console.log(contents)//callApplyBind.html:53 HTMLCollection(3) [div.content, div.content, div.content]0: div.content1: div.content2: div.contentlength: 3__proto__: HTMLCollection

console.log(contents.length)

let contentsArr = Array.prototype.slice.call(contents)
console.log(contentsArr)//callApplyBind.html:58 (3) [div.content, div.content, div.content]

在IE6-8写法:

let ary = []
for(var i =0; i < contents.length; i++){
	ary[ary.length] = contents[i]
}

//基于IE6-8和标准浏览器中的区别,抽取出类数组对象转化为数组的工具类:
function listToArray(likeAry) { 
let ary = [];
try{
    ary = Array.prototype.slice.call(likeAry)
} catch(e){
    for(var i = 0; i < likeAry.length; i++){
        ary[ary.length] = likeAry[i]
    }
}
	return ary;
}

对于arguments借用数组的方法是不存在任何兼容性问题的

function toArray() {
  return Array.prototype.slice.call(arguments)
}
        console.log(toArray(1,4,45,465,65))//callApplyBind.html:82 (5) [1, 4, 45, 465, 65]
 
  • 含有length属性的对象
let anyObj = {
            0:3,
            1:'haier',
            2:44,
            length:3
        };
        console.log(Array.prototype.slice.call(anyObj))//callApplyBind.html:90 (3) [3, "haier", 44]
 
  • 数组拼接,添加
let arr1 = [1, 2, 3];
let arr2 = [4, 5, 6];

let arr3 = arr1.concat(arr2);
console.log(arr3)//callApplyBind.html:96 (6) [1, 2, 3, 4, 5, 6]

console.log(arr1);// [1, 2, 3]
console.log(arr2);// [4, 5, 6]

[].push.apply(arr1,arr2); // 给arr1添加arr2

console.log(arr1);//[1, 2, 3, 4, 5, 6]
console.log(arr2);// [4, 5, 6]

  • 判断变量类型
let ary1 = [1,2,4];
  let str1 = 'str';
  let obj1 = {name:'holmes'};

  function isArray(obj) { 
      return Object.prototype.toString.call(obj) === '[object Array]'
   }

   console.log(isArray(ary1)) // true

   console.log(Object.prototype.toString.call(ary1))//callApplyBind.html:116 [object Array]
   console.log(Object.prototype.toString.call(str1))//callApplyBind.html:116 [object String]
   console.log(Object.prototype.toString.call(obj1))//callApplyBind.html:116 [object Object]
   console.log(Object.prototype.toString.call(null))//callApplyBind.html:119 [object Null]

  • 利用call和apply做继承
function Animal(name) { 
   this.name = name;
    this.showName = function () { 
        console.log(this.name)
     }
 }

 function Cat(name) { 
     Animal.call(this,name);
  }

  let cat = new Cat('mimi');
  cat.showName();//mimi

  • 多继承
function Class1(a,b){
    this.showclass1 = function(a,b){
        console.log(`class1:${a},${b}`)
    }
}  

function Class2(a,b){
    this.showclass2 = function(a,b){
        console.log(`class2:${a},${b}`);
    }
}

function Class3(a,b,c){
    Class1.call(this);
    Class2.call(this);
}

let ary0 = [5,6];
let demo = new Class3();
demo.showclass1.call(this,1);//class1:1,undefined
demo.showclass1.call(this,1,2);//class1:1,2
demo.showclass2.apply(this,ary0);//class2:5,6

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值