call, apply,bind三者都是用于改变对象绑定的this的值,但是在用法上有一些略微的差别。
call (Function.prototype.call())
例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 function Product (name, price ) { this .name = name; this .price = price; } function Food (name, price ) { Product.call(this , name, price); this .category = 'food' ; } console .log(new Food('cheese' , 5 ).name);
自行实现:
1 2 3 4 5 6 7 function callFn (obj, ...arg ) { var _this = obj? obj || window ; _this.fn = this ; var res = _this.fn(...arg); delet _this.fn; return res; }
apply (Function.prototype.apply())
call()方法的作用和 apply() 方法类似,区别就是call()方法接受的是参数列表,而apply()方法接受的是一个参数数组。
例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 function Product (name, price ) { this .name = name; this .price = price; } function Food (name, price ) { Product.apply(this , [name, price]); this .category = 'food' ; } console .log(new Food('cheese' , 5 ).name);
自行实现:
1 2 3 4 5 6 7 function applyFn (object, array ) { var _this = obj? obj || window ; _this.fn = this ; var res = _this.fn(...array); delet _this.fn; return res; }
注意: call的性能比apply的性能好,可以尽可能的去用call
bind (Function.prototype.bind())
bind()方法创建一个新的函数,在bind()被调用时,这个新函数的this被bind的第一个参数指定,其余的参数将作为新函数的参数供调用时使用。
注意: bind函数返回的是一个原函数的拷贝, 并拥有指定的this值和初始参数。
例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 function Product (name, price ) { this .name = name; this .price = price; } function Food (name, price ) { var fn = Product.bind(this , name, price); console .log(res); fn(); this .category = 'food' ; } console .log(new Food('cheese' , 5 ).name);
自行实现:(出自mdn)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 if (!Function .prototype.bind) { Function .prototype.bind = function (oThis ) { if (typeof this !== 'function' ) { throw new TypeError ('Function.prototype.bind - what is trying to be bound is not callable' ); } var aArgs = Array .prototype.slice.call(arguments , 1 ), fToBind = this , fNOP = function ( ) {}, fBound = function ( ) { return fToBind.apply(this instanceof fBound ? this : oThis, aArgs.concat(Array .prototype.slice.call(arguments ))); }; if (this .prototype) { fNOP.prototype = this .prototype; } fBound.prototype = new fNOP(); return fBound; }; }