1.概念javascript
在 javascript 中,call 和 apply 都是为了改变某个函数运行时的上下文(context)而存在的,换句话说,就是为了改变函数体内部 this 的指向。java
2.区别es6
call()和 apply()惟一区别在于传参数,apply()接收两个参数,一个是在其运行函数中的做用域,另一个是参数数组其中,第二参数能够是 Array 的实例,也能够是 arguments 对象,call()第一个参数和 apply()同样,第二个参数必须逐个列举出来,经过代码展现数组
function sum(num1, num2) { return num1 + num2; } function applySum(num1, num2) { console.log(arguments); //此时this对象是全局window对象 return sum.apply(this, arguments); // 或者 return sum.apply(this, [num1, num2]); } console.log(applySum(1, 2)); /** call()和apply()发放惟一区别在于传参数.call()传参数必须逐个列举出来 */ function callSum(num1, num2) { console.log(...arguments); //此时this对象是全局window对象 return sum.call(this, num1, num2); // 或者使用ES6的语法 return sum.call(this, ...arguments); } console.log(callSum(1, 2));
3.传递参数并不是 apply 和 call 的真正的用武之地,他们真正强大的地方是可以扩充函数赖以运行的做用域app
var o = { name: "kebi" }; window.name = "heyushuo"; function sayName() { console.log(this.name); } sayName.call(this); //heyushuo sayName.call(window); //heyushuo sayName.call(o); //kebi 此时函数的执行环境不同了,由于此时函数体内的this对象指向了o,因而结果显示的是'kebi' //call和apply来扩充做用域的最大好处就是对象不须要与方法有任何耦合关系,
4.apply 和 call 的一些骚操做函数
//1.数组合并 var arr1 = [1, 2, 3]; var arr2 = ["heyushuo", "kebi"]; //arr1改变数组的做用域,arr2传的参数 Array.prototype.push.apply(arr1, arr2); //[1,2,3,'heyushuo','kebi'] //或者 arr1.concat(arr2) // 或者ES6的语法 [...arr1, ...arr2]; //2.数组中的最大值 Math.max.apply(Math,arr1); //或者es6的语法 Math.max(...arr1); //3.判断对象的数据类型 //在最原始的对象中进行,不能直接arr1.toString() 或者 o.tosString() 由于对象和数组已经把原始对象的toString()方法进行了修改 Object.prototype.toString.call(arr1); // [object Array] Object.prototype.toString.call(o)); //[object Object] //4.能够把伪数组变成真正的数组,例如 arguments / document.getElementsByTagName("span") Array.prototype.slice.call(document.getElementsByTagName("span"), 0)) //或者使用es6的语法 [...document.getElementsByTagName("span")]
解释: bind()和 call,apply 的做用是同样的,bind()这个方法会建立一个函数的实例,该方法可传入两个参数,第一个参数做为 this,第二个及之后的参数则做为函数的参数调用,这个方法和 call,apply 最重要的区别是,绑定 bind()后会建立一个新的函数,而且不会自动执行,须要调用执行this
//经过这个例子看一下三者的区别 var o = { name: "kebi" }; window.name = "heyushuo"; function sayName() { console.log(this.name); } sayName.call(window); //heyushuo sayName.call(o); //kebi sayName.apply(window); //heyushuo sayName.apply(o); //kebi //这是bind的用法 var objName = sayName.bind(o); //ie9+ objName(); //kebi