JS中call()和apply()以及bind()的区别
一,方法定义
- apply:调用一个对象的一个方法,用另一个对象替换当前对象。例如:B.apply(A, arguments);即A对象应用B对象的方法。
- call:调用一个对象的一个方法,用另一个对象替换当前对象。例如:B.call(A, args1,args2);即A对象调用B对象的方法。
- bind:bind 除了返回是函数以外,它 的参数和 call 一样。
二,功能
bind/apply/call都会改变函数调用时this的指向
三,区别
1,执行方式
apply/call会立即执行该函数,bind是返回绑定this指向后的函数
2,参数
apply/call/bind第一个参数用于this指向改变后的对象
apply其余参数使用数组包裹参数
bind/call参数直接传递
四,比较
let obj ={ name:'obj中的name', print(a,b,c){ console.log(this.name,a,b,c); } } window.name = 'window中的name'; obj.print('1','2','3') obj.print.apply(this,['1','2','3']) obj.print.call(this,'1','2','3') obj.print.bind(this,'1','2','3')() //必须带上(),因为bind()返回的是函数 // 结果 obj中的name 1 2 3 window中的name 1 2 3 window中的name 1 2 3 window中的name 1 2 3
本来print中的this指向调用者obj,但apply,call,bind将this指向全局作用域中的this(即window)
bind()
/** * bind() * bind()方法主要就是将函数绑定到某个对象,bind()会创建一个函数,函数体内的this对象的值会被绑定到传入bind()中的第一个参数的值, * 例如:f.bind(obj),实际上可以理解为obj.f(),这时f函数体内的this自然指向的是obj; */ var a = { b: function() { var func = function() { console.log(this.c); } func(); }, c: 'hello' } a.b(); // undefined 这里的this指向的是全局作用域,在非严格模式下即window,严格模式下undefined console.log(a.c); // hello // 使用bind方法一 var a = { b: function() { var func = function() { console.log(this.c); }.bind(this); func(); }, c: 'hello' } a.b(); // hello console.log(a.c); // hello // 使用bind方法二 var a = { b: function() { var func = function() { console.log(this.c); } func.bind(this)(); }, c: 'hello' } a.b(); // hello console.log(a.c); // hello
如果对一个函数进行多次 bind,那么上下文会是什么呢?
let a = {};
let fn = function () {
console.log(this);
};
fn.bind().bind(a)(); // => ?
不管我们给函数 bind 几次,fn 中的 this 永远由第一次 bind 决定,所以结果是 window。
另外, 在 ES6 的箭头函数下, call 和 apply 将失效,因为箭头函数的特点:
1,体内的 this 对象, 就是定义时所在的对象, 而不是使用时所在的对象
2,箭头函数不可以当作构造函数来用,也就是说不可以使用 new 命令, 否则报错
3,箭头函数不可以使用 arguments 对象,该对象在函数体内不存在,可以用 Rest 参数代替
4,不可以使用 yield 命令, 因此箭头函数不能用作 Generator 函数